fix: dataset selector load error (#4243)

* fix: dataset selector load error

* fix: path auth error

* fix: plugin scroll

* export chat log with contact (#4211)

* export chat log with contact

* fix

---------

Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
Archer 2025-03-20 00:17:10 +08:00 committed by GitHub
parent 70563d2bcb
commit f9cecfd49a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 160 additions and 114 deletions

View File

@ -62,3 +62,4 @@ curl --location --request POST 'https://{{host}}/api/admin/initv491' \
8. 修复 promp 模式工具调用,未判空思考链,导致 UI 错误展示。 8. 修复 promp 模式工具调用,未判空思考链,导致 UI 错误展示。
9. 编辑应用信息导致头像丢失。 9. 编辑应用信息导致头像丢失。
10. 分享链接标题会被刷新掉。 10. 分享链接标题会被刷新掉。
11. 计算 parentPath 时,存在鉴权失败清空。

View File

@ -1,3 +1,8 @@
export type GetPathProps = {
sourceId?: ParentIdType;
type: 'current' | 'parent';
};
export type ParentTreePathItemType = { export type ParentTreePathItemType = {
parentId: string; parentId: string;
parentName: string; parentName: string;

View File

@ -82,7 +82,7 @@
"logs_chat_user": "user", "logs_chat_user": "user",
"logs_empty": "No logs yet~", "logs_empty": "No logs yet~",
"logs_export_confirm_tip": "There are a total of {{total}} dialogue records, confirm the export?", "logs_export_confirm_tip": "There are a total of {{total}} dialogue records, confirm the export?",
"logs_export_title": "Time, source, user, title, total number of messages, user feedback, custom feedback, number of labeled answers, conversation details", "logs_export_title": "Time, source, user, contact, title, total number of messages, user good feedback, user bad feedback, custom feedback, labeled answers, conversation details",
"logs_message_total": "Total Messages", "logs_message_total": "Total Messages",
"logs_source": "source", "logs_source": "source",
"logs_title": "Title", "logs_title": "Title",

View File

@ -82,7 +82,7 @@
"logs_chat_user": "使用者", "logs_chat_user": "使用者",
"logs_empty": "还没有日志噢~", "logs_empty": "还没有日志噢~",
"logs_export_confirm_tip": "当前共 {{total}} 条对话记录,确认导出?", "logs_export_confirm_tip": "当前共 {{total}} 条对话记录,确认导出?",
"logs_export_title": "时间,来源,使用者,标题,消息总数,用户反馈,自定义反馈,标注答案数量,对话详情", "logs_export_title": "时间,来源,使用者,联系方式,标题,消息总数,用户赞同反馈,用户反对反馈,自定义反馈,标注答案,对话详情",
"logs_message_total": "消息总数", "logs_message_total": "消息总数",
"logs_source": "来源", "logs_source": "来源",
"logs_title": "标题", "logs_title": "标题",

View File

@ -82,7 +82,7 @@
"logs_chat_user": "使用者", "logs_chat_user": "使用者",
"logs_empty": "還沒有紀錄喔~", "logs_empty": "還沒有紀錄喔~",
"logs_export_confirm_tip": "當前共 {{total}} 條對話記錄,確認導出?", "logs_export_confirm_tip": "當前共 {{total}} 條對話記錄,確認導出?",
"logs_export_title": "時間,來源,使用者,標題,消息總數,用戶反饋,自定義反饋,標註答案數量,對話詳情", "logs_export_title": "時間,來源,使用者,聯繫方式,標題,消息總數,用戶贊同反饋,用戶反對反饋,自定義反饋,標註答案,對話詳情",
"logs_message_total": "訊息總數", "logs_message_total": "訊息總數",
"logs_source": "来源", "logs_source": "来源",
"logs_title": "標題", "logs_title": "標題",

View File

@ -40,26 +40,10 @@ export const DatasetSelectModal = ({
const { paths, setParentId, datasets, isFetching } = useDatasetSelect(); const { paths, setParentId, datasets, isFetching } = useDatasetSelect();
const { Loading } = useLoading(); const { Loading } = useLoading();
const filterDatasets = useMemo(() => { const unSelectedDatasets = useMemo(() => {
const selectedInDatasets = datasets.filter((item) => return datasets.filter(
selectedDatasets.some((dataset) => dataset.datasetId === item._id) (item) => !selectedDatasets.some((dataset) => dataset.datasetId === item._id)
); );
const selectedNotInDatasets = selectedDatasets
.filter((selected) => !datasets.some((dataset) => dataset._id === selected.datasetId))
.map((selected) => ({
_id: selected.datasetId,
avatar: selected.avatar,
name: selected.name,
vectorModel: selected.vectorModel
}));
return {
selected: [...selectedInDatasets, ...selectedNotInDatasets],
unSelected: datasets.filter(
(item) => !selectedDatasets.some((dataset) => dataset.datasetId === item._id)
)
};
}, [datasets, selectedDatasets]); }, [datasets, selectedDatasets]);
const activeVectorModel = selectedDatasets[0]?.vectorModel?.model; const activeVectorModel = selectedDatasets[0]?.vectorModel?.model;
@ -82,11 +66,11 @@ export const DatasetSelectModal = ({
]} ]}
gridGap={3} gridGap={3}
> >
{filterDatasets.selected.map((item) => {selectedDatasets.map((item) =>
(() => { (() => {
return ( return (
<Card <Card
key={item._id} key={item.datasetId}
p={3} p={3}
border={theme.borders.base} border={theme.borders.base}
boxShadow={'sm'} boxShadow={'sm'}
@ -104,7 +88,7 @@ export const DatasetSelectModal = ({
_hover={{ color: 'red.500' }} _hover={{ color: 'red.500' }}
onClick={() => { onClick={() => {
setSelectedDatasets((state) => setSelectedDatasets((state) =>
state.filter((dataset) => dataset.datasetId !== item._id) state.filter((dataset) => dataset.datasetId !== item.datasetId)
); );
}} }}
/> />
@ -115,7 +99,7 @@ export const DatasetSelectModal = ({
)} )}
</Grid> </Grid>
{filterDatasets.selected.length > 0 && <Divider my={3} />} {selectedDatasets.length > 0 && <Divider my={3} />}
<Grid <Grid
gridTemplateColumns={[ gridTemplateColumns={[
@ -125,7 +109,7 @@ export const DatasetSelectModal = ({
]} ]}
gridGap={3} gridGap={3}
> >
{filterDatasets.unSelected.map((item) => {unSelectedDatasets.map((item) =>
(() => { (() => {
return ( return (
<MyTooltip <MyTooltip
@ -203,9 +187,7 @@ export const DatasetSelectModal = ({
})() })()
)} )}
</Grid> </Grid>
{filterDatasets.unSelected.length === 0 && ( {unSelectedDatasets.length === 0 && <EmptyTip text={t('common:common.folder.empty')} />}
<EmptyTip text={t('common:common.folder.empty')} />
)}
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>

View File

@ -6,6 +6,7 @@ import { useTranslation } from 'next-i18next';
import { Box } from '@chakra-ui/react'; import { Box } from '@chakra-ui/react';
import ParentPaths from '@/components/common/ParentPaths'; import ParentPaths from '@/components/common/ParentPaths';
import MyBox from '@fastgpt/web/components/common/MyBox'; import MyBox from '@fastgpt/web/components/common/MyBox';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
type PathItemType = { type PathItemType = {
parentId: string; parentId: string;
@ -70,8 +71,16 @@ const DatasetSelectContainer = ({
export function useDatasetSelect() { export function useDatasetSelect() {
const [parentId, setParentId] = useState<string>(''); const [parentId, setParentId] = useState<string>('');
const { data, isFetching } = useQuery(['loadDatasetData', parentId], () => const { data, loading: isFetching } = useRequest2(
Promise.all([getDatasets({ parentId }), getDatasetPaths(parentId)]) () =>
Promise.all([
getDatasets({ parentId }),
getDatasetPaths({ sourceId: parentId, type: 'current' })
]),
{
manual: false,
refreshDeps: [parentId]
}
); );
const paths = useMemo(() => [...(data?.[1] || [])], [data]); const paths = useMemo(() => [...(data?.[1] || [])], [data]);

View File

@ -61,10 +61,13 @@ const Header = ({
const { lastAppListRouteType } = useSystemStore(); const { lastAppListRouteType } = useSystemStore();
const { data: paths = [] } = useRequest2(() => getAppFolderPath(appId), { const { data: paths = [] } = useRequest2(
manual: false, () => getAppFolderPath({ sourceId: appId, type: 'parent' }),
refreshDeps: [appId] {
}); manual: false,
refreshDeps: [appId]
}
);
const onClickRoute = useCallback( const onClickRoute = useCallback(
(parentId: string) => { (parentId: string) => {
router.push({ router.push({

View File

@ -112,8 +112,9 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void })
const { data: paths = [] } = useRequest2( const { data: paths = [] } = useRequest2(
() => { () => {
if (templateType === TemplateTypeEnum.teamPlugin) return getAppFolderPath(parentId); if (templateType === TemplateTypeEnum.teamPlugin)
return getSystemPluginPaths(parentId); return getAppFolderPath({ sourceId: parentId, type: 'current' });
return getSystemPluginPaths({ sourceId: parentId, type: 'current' });
}, },
{ {
manual: false, manual: false,
@ -186,7 +187,7 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void })
{/* route components */} {/* route components */}
{!searchKey && parentId && ( {!searchKey && parentId && (
<Flex mt={2} px={[3, 6]}> <Flex mt={2} px={[3, 6]}>
<FolderPath paths={paths} FirstPathDom={null} onClick={() => onUpdateParentId(null)} /> <FolderPath paths={paths} FirstPathDom={null} onClick={onUpdateParentId} />
</Flex> </Flex>
)} )}
<MyBox isLoading={isLoading} mt={2} px={[3, 6]} pb={3} flex={'1 0 0'} overflowY={'auto'}> <MyBox isLoading={isLoading} mt={2} px={[3, 6]} pb={3} flex={'1 0 0'} overflowY={'auto'}>

View File

@ -144,7 +144,7 @@ const ChatTest = ({ isOpen, nodes = [], edges = [], onClose }: Props) => {
</Flex> </Flex>
)} )}
<Flex flex={'1 0 0'} alignItems={'end'}> <Flex flex={'1 0 0'} alignItems={'end'} h={'100%'}>
<Box flex={'1 0 0'} h={'100%'} overflow={'auto'}> <Box flex={'1 0 0'} h={'100%'} overflow={'auto'}>
<ChatContainer /> <ChatContainer />
</Box> </Box>

View File

@ -276,8 +276,9 @@ const RenderHeader = React.memo(function RenderHeader({
// Get paths // Get paths
const { data: paths = [] } = useRequest2( const { data: paths = [] } = useRequest2(
() => { () => {
if (templateType === TemplateTypeEnum.teamPlugin) return getAppFolderPath(parentId); if (templateType === TemplateTypeEnum.teamPlugin)
return getSystemPluginPaths(parentId); return getAppFolderPath({ sourceId: parentId, type: 'current' });
return getSystemPluginPaths({ sourceId: parentId, type: 'current' });
}, },
{ {
manual: false, manual: false,

View File

@ -126,7 +126,7 @@ export const useChatTest = ({
const CustomChatContainer = useMemoizedFn(() => const CustomChatContainer = useMemoizedFn(() =>
appDetail.type === AppTypeEnum.plugin ? ( appDetail.type === AppTypeEnum.plugin ? (
<Box p={5}> <Box p={5} pb={16}>
<PluginRunBox <PluginRunBox
appId={appId} appId={appId}
chatId={chatId} chatId={chatId}

View File

@ -90,7 +90,7 @@ const AppListContextProvider = ({ children }: { children: ReactNode }) => {
); );
const { data: paths = [], runAsync: refetchPaths } = useRequest2( const { data: paths = [], runAsync: refetchPaths } = useRequest2(
() => getAppFolderPath(parentId), () => getAppFolderPath({ sourceId: parentId, type: 'current' }),
{ {
manual: false, manual: false,
refreshDeps: [parentId] refreshDeps: [parentId]

View File

@ -18,6 +18,10 @@ import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSc
import { ChatItemValueTypeEnum, ChatSourceEnum } from '@fastgpt/global/core/chat/constants'; import { ChatItemValueTypeEnum, ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
import { AIChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import { AIChatItemValueItemType } from '@fastgpt/global/core/chat/type';
const formatJsonString = (data: any) => {
return JSON.stringify(data).replace(/"/g, '""').replace(/\n/g, '\\n');
};
export type ExportChatLogsBody = GetAppChatLogsProps & { export type ExportChatLogsBody = GetAppChatLogsProps & {
title: string; title: string;
sourcesMap: Record<string, { label: string }>; sourcesMap: Record<string, { label: string }>;
@ -40,7 +44,30 @@ async function handler(req: ApiRequestProps<ExportChatLogsBody, {}>, res: NextAp
} }
const { teamId } = await authApp({ req, authToken: true, appId, per: WritePermissionVal }); const { teamId } = await authApp({ req, authToken: true, appId, per: WritePermissionVal });
const teamMembers = await MongoTeamMember.find({ teamId });
const teamMemberWithContact = await MongoTeamMember.aggregate([
{ $match: { teamId: new Types.ObjectId(teamId) } },
{
$lookup: {
from: 'users',
localField: 'userId',
foreignField: '_id',
as: 'user'
}
},
{
$project: {
memberId: '$_id',
teamId: 1,
userId: 1,
name: 1,
role: 1,
status: 1,
contact: { $ifNull: [{ $arrayElemAt: ['$user.contact', 0] }, '-'] }
}
}
]);
console.log(teamMemberWithContact);
const where = { const where = {
teamId: new Types.ObjectId(teamId), teamId: new Types.ObjectId(teamId),
@ -104,40 +131,32 @@ async function handler(req: ApiRequestProps<ExportChatLogsBody, {}>, res: NextAp
}, },
{ {
$addFields: { $addFields: {
userGoodFeedbackCount: { userGoodFeedbackItems: {
$size: { $filter: {
$filter: { input: '$chatitems',
input: '$chatitems', as: 'item',
as: 'item', cond: { $ifNull: ['$$item.userGoodFeedback', false] }
cond: { $ifNull: ['$$item.userGoodFeedback', false] }
}
} }
}, },
userBadFeedbackCount: { userBadFeedbackItems: {
$size: { $filter: {
$filter: { input: '$chatitems',
input: '$chatitems', as: 'item',
as: 'item', cond: { $ifNull: ['$$item.userBadFeedback', false] }
cond: { $ifNull: ['$$item.userBadFeedback', false] }
}
} }
}, },
customFeedbacksCount: { customFeedbackItems: {
$size: { $filter: {
$filter: { input: '$chatitems',
input: '$chatitems', as: 'item',
as: 'item', cond: { $gt: [{ $size: { $ifNull: ['$$item.customFeedbacks', []] } }, 0] }
cond: { $gt: [{ $size: { $ifNull: ['$$item.customFeedbacks', []] } }, 0] }
}
} }
}, },
markCount: { markItems: {
$size: { $filter: {
$filter: { input: '$chatitems',
input: '$chatitems', as: 'item',
as: 'item', cond: { $ifNull: ['$$item.adminFeedback', false] }
cond: { $ifNull: ['$$item.adminFeedback', false] }
}
} }
}, },
chatDetails: { chatDetails: {
@ -161,10 +180,10 @@ async function handler(req: ApiRequestProps<ExportChatLogsBody, {}>, res: NextAp
source: 1, source: 1,
time: '$updateTime', time: '$updateTime',
messageCount: { $size: '$chatitems' }, messageCount: { $size: '$chatitems' },
userGoodFeedbackCount: 1, userGoodFeedbackItems: 1,
userBadFeedbackCount: 1, userBadFeedbackItems: 1,
customFeedbacksCount: 1, customFeedbackItems: 1,
markCount: 1, markItems: 1,
outLinkUid: 1, outLinkUid: 1,
tmbId: 1, tmbId: 1,
chatDetails: 1 chatDetails: 1
@ -187,14 +206,18 @@ async function handler(req: ApiRequestProps<ExportChatLogsBody, {}>, res: NextAp
const time = dayjs(doc.time.toISOString()).format('YYYY-MM-DD HH:mm:ss'); const time = dayjs(doc.time.toISOString()).format('YYYY-MM-DD HH:mm:ss');
const source = sourcesMap[doc.source as ChatSourceEnum]?.label || doc.source; const source = sourcesMap[doc.source as ChatSourceEnum]?.label || doc.source;
const title = doc.customTitle || doc.title; const title = doc.customTitle || doc.title;
const tmb = doc.outLinkUid const tmbName = doc.outLinkUid
? doc.outLinkUid ? doc.outLinkUid
: teamMembers.find((member) => String(member._id) === String(doc.tmbId))?.name; : teamMemberWithContact.find((member) => String(member.memberId) === String(doc.tmbId))?.name;
const tmbContact = teamMemberWithContact.find(
(member) => String(member.memberId) === String(doc.tmbId)
)?.contact;
const messageCount = doc.messageCount; const messageCount = doc.messageCount;
const userFeedbackCount = doc.userGoodFeedbackCount || doc.userBadFeedbackCount || '-'; const userGoodFeedbackItems = doc.userGoodFeedbackItems || [];
const customFeedbacksCount = doc.customFeedbacksCount || '-'; const userBadFeedbackItems = doc.userBadFeedbackItems || [];
const markCount = doc.markCount; const customFeedbackItems = doc.customFeedbackItems || [];
const markItems = doc.markItems || [];
const chatDetails = doc.chatDetails.map( const chatDetails = doc.chatDetails.map(
(chat: { id: string; value: AIChatItemValueItemType[] }) => { (chat: { id: string; value: AIChatItemValueItemType[] }) => {
return chat.value.map((item) => { return chat.value.map((item) => {
@ -228,9 +251,14 @@ async function handler(req: ApiRequestProps<ExportChatLogsBody, {}>, res: NextAp
}); });
} }
); );
let chatDetailsStr = JSON.stringify(chatDetails).replace(/"/g, '""').replace(/\n/g, '\\n');
const res = `\n"${time}","${source}","${tmb}","${title}","${messageCount}","${userFeedbackCount}","${customFeedbacksCount}","${markCount}","${chatDetailsStr}"`; const userGoodFeedbackItemsStr = formatJsonString(userGoodFeedbackItems);
const userBadFeedbackItemsStr = formatJsonString(userBadFeedbackItems);
const customFeedbackItemsStr = formatJsonString(customFeedbackItems);
const markItemsStr = formatJsonString(markItems);
const chatDetailsStr = formatJsonString(chatDetails);
const res = `\n"${time}","${source}","${tmbName}","${tmbContact}","${title}","${messageCount}","${userGoodFeedbackItemsStr}","${userBadFeedbackItemsStr}","${customFeedbackItemsStr}","${markItemsStr}","${chatDetailsStr}"`;
write(res); write(res);
}); });

View File

@ -1,5 +1,6 @@
import type { NextApiRequest, NextApiResponse } from 'next'; import type { NextApiRequest, NextApiResponse } from 'next';
import type { import type {
GetPathProps,
ParentIdType, ParentIdType,
ParentTreePathItemType ParentTreePathItemType
} from '@fastgpt/global/common/parentFolder/type.d'; } from '@fastgpt/global/common/parentFolder/type.d';
@ -12,15 +13,15 @@ async function handler(
req: NextApiRequest, req: NextApiRequest,
res: NextApiResponse<any> res: NextApiResponse<any>
): Promise<ParentTreePathItemType[]> { ): Promise<ParentTreePathItemType[]> {
const { parentId } = req.query as { parentId: string }; const { sourceId: appId, type } = req.query as GetPathProps;
if (!parentId) { if (!appId) {
return []; return [];
} }
await authApp({ req, authToken: true, appId: parentId, per: ReadPermissionVal }); const { app } = await authApp({ req, authToken: true, appId, per: ReadPermissionVal });
return await getParents(parentId); return await getParents(type === 'current' ? appId : app.parentId);
} }
export default NextAPI(handler); export default NextAPI(handler);

View File

@ -1,11 +1,9 @@
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { ParentIdType, ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type'; import { GetPathProps, ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
import { getSystemPlugins } from '@/service/core/app/plugin'; import { getSystemPlugins } from '@/service/core/app/plugin';
export type pathQuery = { export type pathQuery = GetPathProps;
parentId: ParentIdType;
};
export type pathBody = {}; export type pathBody = {};
@ -15,18 +13,18 @@ async function handler(
req: ApiRequestProps<pathBody, pathQuery>, req: ApiRequestProps<pathBody, pathQuery>,
res: ApiResponseType<any> res: ApiResponseType<any>
): Promise<pathResponse> { ): Promise<pathResponse> {
const { parentId } = req.query; const { sourceId: pluginId, type } = req.query;
if (!parentId) return []; if (!pluginId) return [];
const plugins = await getSystemPlugins(); const plugins = await getSystemPlugins();
const plugin = plugins.find((item) => item.id === parentId); const plugin = plugins.find((item) => item.id === pluginId);
if (!plugin) return []; if (!plugin) return [];
return [ return [
{ {
parentId: plugin.id, parentId: type === 'current' ? plugin.id : plugin.parentId,
parentName: plugin.name parentName: plugin.name
} }
]; ];

View File

@ -1,20 +1,28 @@
import type { NextApiRequest } from 'next'; import type { NextApiRequest } from 'next';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema'; import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import type { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type.d'; import type {
GetPathProps,
ParentTreePathItemType
} from '@fastgpt/global/common/parentFolder/type.d';
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth'; import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
async function handler(req: NextApiRequest) { async function handler(req: NextApiRequest) {
const { parentId } = req.query as { parentId: string }; const { sourceId: datasetId, type } = req.query as GetPathProps;
if (!parentId) { if (!datasetId) {
return []; return [];
} }
await authDataset({ req, authToken: true, datasetId: parentId, per: ReadPermissionVal }); const { dataset } = await authDataset({
req,
authToken: true,
datasetId,
per: ReadPermissionVal
});
return await getParents(parentId); return await getParents(type === 'current' ? dataset._id : dataset.parentId);
} }
async function getParents(parentId?: string): Promise<ParentTreePathItemType[]> { async function getParents(parentId?: string): Promise<ParentTreePathItemType[]> {

View File

@ -97,10 +97,10 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
); );
const { data: paths = [], runAsync: refetchPaths } = useRequest2( const { data: paths = [], runAsync: refetchPaths } = useRequest2(
() => getDatasetPaths(parentId), async () => getDatasetPaths({ sourceId: parentId, type: 'current' }),
{ {
manual: false, manual: false,
refreshDeps: [parentId] refreshDeps: [folderDetail]
} }
); );

View File

@ -1,7 +1,9 @@
import { DELETE, GET, POST } from '@/web/common/api/request'; import { DELETE, GET, POST } from '@/web/common/api/request';
import type { CreateAppFolderBody } from '@/pages/api/core/app/folder/create'; import type { CreateAppFolderBody } from '@/pages/api/core/app/folder/create';
import type { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type'; import type {
import type { ParentIdType } from '@fastgpt/global/common/parentFolder/type'; GetPathProps,
ParentTreePathItemType
} from '@fastgpt/global/common/parentFolder/type';
import type { import type {
transitionWorkflowBody, transitionWorkflowBody,
transitionWorkflowResponse transitionWorkflowResponse
@ -12,10 +14,10 @@ import type { copyAppQuery, copyAppResponse } from '@/pages/api/core/app/copy';
export const postCreateAppFolder = (data: CreateAppFolderBody) => export const postCreateAppFolder = (data: CreateAppFolderBody) =>
POST('/core/app/folder/create', data); POST('/core/app/folder/create', data);
export const getAppFolderPath = (parentId: ParentIdType) => { export const getAppFolderPath = (data: GetPathProps) => {
if (!parentId) return Promise.resolve<ParentTreePathItemType[]>([]); if (!data.sourceId) return Promise.resolve<ParentTreePathItemType[]>([]);
return GET<ParentTreePathItemType[]>(`/core/app/folder/path`, { parentId }); return GET<ParentTreePathItemType[]>(`/core/app/folder/path`, data);
}; };
/* detail */ /* detail */

View File

@ -12,6 +12,7 @@ import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constant
import type { GetPreviewNodeQuery } from '@/pages/api/core/app/plugin/getPreviewNode'; import type { GetPreviewNodeQuery } from '@/pages/api/core/app/plugin/getPreviewNode';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import type { import type {
GetPathProps,
ParentIdType, ParentIdType,
ParentTreePathItemType ParentTreePathItemType
} from '@fastgpt/global/common/parentFolder/type'; } from '@fastgpt/global/common/parentFolder/type';
@ -53,9 +54,9 @@ export const getPluginGroups = () => {
: Promise.resolve([defaultGroup]); : Promise.resolve([defaultGroup]);
}; };
export const getSystemPluginPaths = (parentId: ParentIdType) => { export const getSystemPluginPaths = (data: GetPathProps) => {
if (!parentId) return Promise.resolve<ParentTreePathItemType[]>([]); if (!data.sourceId) return Promise.resolve<ParentTreePathItemType[]>([]);
return GET<ParentTreePathItemType[]>('/core/app/plugin/path', { parentId }); return GET<ParentTreePathItemType[]>('/core/app/plugin/path', data);
}; };
export const getPreviewPluginNode = (data: GetPreviewNodeQuery) => export const getPreviewPluginNode = (data: GetPreviewNodeQuery) =>

View File

@ -1,5 +1,6 @@
import { GET, POST, PUT, DELETE } from '@/web/common/api/request'; import { GET, POST, PUT, DELETE } from '@/web/common/api/request';
import type { import type {
GetPathProps,
ParentIdType, ParentIdType,
ParentTreePathItemType ParentTreePathItemType
} from '@fastgpt/global/common/parentFolder/type.d'; } from '@fastgpt/global/common/parentFolder/type.d';
@ -77,8 +78,10 @@ export const getDatasetsByAppIdAndDatasetIds = (data: { appId: string; datasetId
* get type=dataset list * get type=dataset list
*/ */
export const getDatasetPaths = (parentId: ParentIdType) => export const getDatasetPaths = (data: GetPathProps) => {
GET<ParentTreePathItemType[]>('/core/dataset/paths', { parentId }); if (!data.sourceId) return Promise.resolve([]);
return GET<ParentTreePathItemType[]>('/core/dataset/paths', data);
};
export const getDatasetById = (id: string) => GET<DatasetItemType>(`/core/dataset/detail?id=${id}`); export const getDatasetById = (id: string) => GET<DatasetItemType>(`/core/dataset/detail?id=${id}`);

View File

@ -250,7 +250,10 @@ export const DatasetPageContextProvider = ({
const { data: paths = [], runAsync: refetchPaths } = useRequest2( const { data: paths = [], runAsync: refetchPaths } = useRequest2(
() => () =>
getDatasetPaths(datasetDetail.parentId).then((res) => { getDatasetPaths({
sourceId: datasetDetail?._id,
type: 'parent'
}).then((res) => {
res.push({ res.push({
parentId: '', parentId: '',
parentName: datasetDetail.name parentName: datasetDetail.name