mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-01 03:48:24 +00:00
Concat plugin to app (#1799)
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
@@ -21,9 +23,10 @@ export const useAudioPlay = (props?: OutLinkChatAuthProps & { ttsConfig?: AppTTS
|
||||
|
||||
// Check whether the voice is supported
|
||||
const hasAudio = (() => {
|
||||
if (typeof window === 'undefined') return false;
|
||||
if (ttsConfig?.type === TTSTypeEnum.none) return false;
|
||||
if (ttsConfig?.type === TTSTypeEnum.model) return true;
|
||||
const voices = window.speechSynthesis?.getVoices?.() || []; // 获取语言包
|
||||
const voices = window?.speechSynthesis?.getVoices?.() || []; // 获取语言包
|
||||
const voice = voices.find((item) => {
|
||||
return item.lang === 'zh-CN' || item.lang === 'zh';
|
||||
});
|
||||
@@ -69,9 +72,9 @@ export const useAudioPlay = (props?: OutLinkChatAuthProps & { ttsConfig?: AppTTS
|
||||
);
|
||||
const playWebAudio = useCallback((text: string) => {
|
||||
// window speech
|
||||
window.speechSynthesis?.cancel();
|
||||
window?.speechSynthesis?.cancel();
|
||||
const msg = new SpeechSynthesisUtterance(text);
|
||||
const voices = window.speechSynthesis?.getVoices?.() || []; // 获取语言包
|
||||
const voices = window?.speechSynthesis?.getVoices?.() || []; // 获取语言包
|
||||
const voice = voices.find((item) => {
|
||||
return item.lang === 'zh-CN';
|
||||
});
|
||||
|
@@ -2,6 +2,10 @@ import { DELETE, GET, POST } from '@/web/common/api/request';
|
||||
import type { CreateAppFolderBody } from '@/pages/api/core/app/folder/create';
|
||||
import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import type {
|
||||
transitionWorkflowBody,
|
||||
transitionWorkflowResponse
|
||||
} from '@/pages/api/core/app/transitionWorkflow';
|
||||
|
||||
/* folder */
|
||||
export const postCreateAppFolder = (data: CreateAppFolderBody) =>
|
||||
@@ -9,3 +13,8 @@ export const postCreateAppFolder = (data: CreateAppFolderBody) =>
|
||||
|
||||
export const getAppFolderPath = (parentId: ParentIdType) =>
|
||||
GET<ParentTreePathItemType[]>(`/core/app/folder/path`, { parentId });
|
||||
|
||||
/* detail */
|
||||
|
||||
export const postTransition2Workflow = (data: transitionWorkflowBody) =>
|
||||
POST<transitionWorkflowResponse>('/core/app/transitionWorkflow', data);
|
||||
|
50
projects/app/src/web/core/app/api/plugin.ts
Normal file
50
projects/app/src/web/core/app/api/plugin.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { DELETE, GET, POST } from '@/web/common/api/request';
|
||||
import type { createHttpPluginBody } from '@/pages/api/core/app/httpPlugin/create';
|
||||
import type { UpdateHttpPluginBody } from '@/pages/api/core/app/httpPlugin/update';
|
||||
import { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type';
|
||||
import { getMyApps } from '../api';
|
||||
import type { ListAppBody } from '@/pages/api/core/app/list';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import type { GetPreviewNodeQuery } from '@/pages/api/core/app/plugin/getPreviewNode';
|
||||
|
||||
/* ============ team plugin ============== */
|
||||
export const getTeamPlugTemplates = (data?: ListAppBody) =>
|
||||
getMyApps(data).then((res) =>
|
||||
res.map<FlowNodeTemplateType>((app) => ({
|
||||
id: app._id,
|
||||
pluginId: app._id,
|
||||
pluginType: app.type,
|
||||
templateType: FlowNodeTemplateTypeEnum.personalPlugin,
|
||||
flowNodeType: FlowNodeTypeEnum.pluginModule,
|
||||
avatar: app.avatar,
|
||||
name: app.name,
|
||||
intro: app.intro,
|
||||
showStatus: false,
|
||||
version: app.pluginData?.nodeVersion || '481',
|
||||
inputs: [],
|
||||
outputs: []
|
||||
}))
|
||||
);
|
||||
|
||||
export const getSystemPlugTemplates = () =>
|
||||
GET<FlowNodeTemplateType[]>('/core/app/plugin/getSystemPluginTemplates');
|
||||
|
||||
export const getPreviewPluginNode = (data: GetPreviewNodeQuery) =>
|
||||
GET<FlowNodeTemplateType>('/core/app/plugin/getPreviewNode', data);
|
||||
|
||||
/* ============ http plugin ============== */
|
||||
export const postCreateHttpPlugin = (data: createHttpPluginBody) =>
|
||||
POST('/core/app/httpPlugin/create', data);
|
||||
|
||||
export const putUpdateHttpPlugin = (body: UpdateHttpPluginBody) =>
|
||||
POST('/core/app/httpPlugin/update', body);
|
||||
|
||||
export const getApiSchemaByUrl = (url: string) =>
|
||||
POST<Object>(
|
||||
'/core/app/httpPlugin/getApiSchemaByUrl',
|
||||
{ url },
|
||||
{
|
||||
timeout: 30000
|
||||
}
|
||||
);
|
@@ -2,6 +2,13 @@ import { PostPublishAppProps, PostRevertAppProps } from '@/global/core/app/api';
|
||||
import { GET, POST, DELETE, PUT } from '@/web/common/api/request';
|
||||
import { AppVersionSchemaType } from '@fastgpt/global/core/app/version';
|
||||
import { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/type';
|
||||
import type {
|
||||
getLatestVersionQuery,
|
||||
getLatestVersionResponse
|
||||
} from '@/pages/api/core/app/version/latest';
|
||||
|
||||
export const getAppLatestVersion = (data: getLatestVersionQuery) =>
|
||||
GET<getLatestVersionResponse>('/core/app/version/latest', data);
|
||||
|
||||
export const postPublishApp = (appId: string, data: PostPublishAppProps) =>
|
||||
POST(`/core/app/version/publish?appId=${appId}`, data);
|
@@ -1,114 +0,0 @@
|
||||
import { Dispatch, ReactNode, SetStateAction, useCallback, useState } from 'react';
|
||||
import { createContext } from 'use-context-selector';
|
||||
import { defaultApp } from '../constants';
|
||||
import { getAppDetailById, putAppById } from '../api';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { AppDetailType } from '@fastgpt/global/core/app/type';
|
||||
import { AppUpdateParams, PostPublishAppProps } from '@/global/core/app/api';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { postPublishApp } from '../versionApi';
|
||||
|
||||
type AppContextType = {
|
||||
appDetail: AppDetailType;
|
||||
setAppDetail: Dispatch<SetStateAction<AppDetailType>>;
|
||||
loadingApp: boolean;
|
||||
updateAppDetail: (data: AppUpdateParams) => Promise<void>;
|
||||
publishApp: (data: PostPublishAppProps) => Promise<void>;
|
||||
};
|
||||
|
||||
export const AppContext = createContext<AppContextType>({
|
||||
appDetail: defaultApp,
|
||||
setAppDetail: function (value: SetStateAction<AppDetailType>): void {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
loadingApp: false,
|
||||
updateAppDetail: function (data: AppUpdateParams): Promise<void> {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
publishApp: function (data: PostPublishAppProps): Promise<void> {
|
||||
throw new Error('Function not implemented.');
|
||||
}
|
||||
});
|
||||
|
||||
export const AppContextProvider = ({ children, appId }: { children: ReactNode; appId: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
const [appDetail, setAppDetail] = useState(defaultApp);
|
||||
|
||||
const { loading } = useRequest(
|
||||
() => {
|
||||
if (appId) {
|
||||
return getAppDetailById(appId);
|
||||
}
|
||||
return Promise.resolve(defaultApp);
|
||||
},
|
||||
{
|
||||
refreshDeps: [appId],
|
||||
onSuccess(res) {
|
||||
setAppDetail(res);
|
||||
},
|
||||
onError(err: any) {
|
||||
toast({
|
||||
title: err?.message || t('core.app.error.Get app failed'),
|
||||
status: 'error'
|
||||
});
|
||||
router.replace('/app/list');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const updateAppDetail = useCallback(
|
||||
async (data: AppUpdateParams) => {
|
||||
try {
|
||||
await putAppById(appId, data);
|
||||
setAppDetail((state) => {
|
||||
return {
|
||||
...state,
|
||||
...data,
|
||||
modules: data?.nodes || state.modules
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: getErrText(error)
|
||||
});
|
||||
}
|
||||
},
|
||||
[appId, toast]
|
||||
);
|
||||
const publishApp = useCallback(
|
||||
async (data: PostPublishAppProps) => {
|
||||
try {
|
||||
await postPublishApp(appId, data);
|
||||
setAppDetail((state) => {
|
||||
return {
|
||||
...state,
|
||||
...data,
|
||||
modules: data?.nodes || state.modules
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: getErrText(error)
|
||||
});
|
||||
}
|
||||
},
|
||||
[appId, toast]
|
||||
);
|
||||
|
||||
const contextValue = {
|
||||
appDetail,
|
||||
setAppDetail,
|
||||
loadingApp: loading,
|
||||
updateAppDetail,
|
||||
publishApp
|
||||
};
|
||||
|
||||
return <AppContext.Provider value={contextValue}>{children}</AppContext.Provider>;
|
||||
};
|
@@ -7,12 +7,14 @@ import {
|
||||
FlowNodeTypeEnum
|
||||
} from '@fastgpt/global/core/workflow/node/constant';
|
||||
|
||||
// template
|
||||
export const appTemplates: (AppItemType & {
|
||||
type TemplateType = (AppItemType & {
|
||||
avatar: string;
|
||||
intro: string;
|
||||
type: AppTypeEnum;
|
||||
})[] = [
|
||||
})[];
|
||||
|
||||
// template
|
||||
export const simpleBotTemplates: TemplateType = [
|
||||
{
|
||||
id: 'simpleChat',
|
||||
avatar: '/imgs/workflow/AI.png',
|
||||
@@ -817,13 +819,16 @@ export const appTemplates: (AppItemType & {
|
||||
targetHandle: '7BdojPlukIQw-target-left'
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
export const workflowTemplates: TemplateType = [
|
||||
{
|
||||
id: 'CQ',
|
||||
avatar: '/imgs/workflow/cq.png',
|
||||
name: '问题分类 + 知识库',
|
||||
intro: '先对用户的问题进行分类,再根据不同类型问题,执行不同的操作',
|
||||
type: AppTypeEnum.advanced,
|
||||
type: AppTypeEnum.workflow,
|
||||
modules: [
|
||||
{
|
||||
nodeId: 'userGuide',
|
||||
@@ -1273,3 +1278,46 @@ export const appTemplates: (AppItemType & {
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export const pluginTemplates: TemplateType = [
|
||||
{
|
||||
id: 'plugin-simple',
|
||||
avatar: '/imgs/workflow/AI.png',
|
||||
name: '默认模板',
|
||||
intro: '标准的插件初始模板',
|
||||
type: AppTypeEnum.plugin,
|
||||
modules: [
|
||||
{
|
||||
nodeId: 'pluginInput',
|
||||
name: '自定义插件输入',
|
||||
avatar: '/imgs/workflow/input.png',
|
||||
flowNodeType: FlowNodeTypeEnum.pluginInput,
|
||||
showStatus: false,
|
||||
position: {
|
||||
x: 616.4226348688949,
|
||||
y: -165.05298493910115
|
||||
},
|
||||
version: '481',
|
||||
inputs: [],
|
||||
outputs: []
|
||||
},
|
||||
{
|
||||
nodeId: 'pluginOutput',
|
||||
name: '自定义插件输出',
|
||||
avatar: '/imgs/workflow/output.png',
|
||||
flowNodeType: FlowNodeTypeEnum.pluginOutput,
|
||||
showStatus: false,
|
||||
position: {
|
||||
x: 1607.7142331269126,
|
||||
y: -151.8669210746189
|
||||
},
|
||||
version: '481',
|
||||
inputs: [],
|
||||
outputs: []
|
||||
}
|
||||
],
|
||||
edges: []
|
||||
}
|
||||
];
|
||||
|
||||
export const defaultAppTemplates = simpleBotTemplates.concat(workflowTemplates[0]);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
AppChatConfigType,
|
||||
AppDetailType,
|
||||
ChatInputGuideConfigType,
|
||||
AppSchema,
|
||||
AppSimpleEditFormType
|
||||
} from '@fastgpt/global/core/app/type';
|
||||
@@ -16,12 +16,15 @@ import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import { StoreEdgeItemType } from '@fastgpt/global/core/workflow/type/edge';
|
||||
import { EditorVariablePickerType } from '@fastgpt/web/components/common/Textarea/PromptEditor/type';
|
||||
import { TFunction } from 'next-i18next';
|
||||
import { ToolModule } from '@fastgpt/global/core/workflow/template/system/tools';
|
||||
|
||||
type WorkflowType = {
|
||||
nodes: StoreNodeItemType[];
|
||||
edges: StoreEdgeItemType[];
|
||||
};
|
||||
export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
|
||||
export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType & {
|
||||
chatConfig: AppChatConfigType;
|
||||
} {
|
||||
const workflowStartNodeId = 'workflowStartNodeId';
|
||||
function systemConfigTemplate(formData: AppSimpleEditFormType): StoreNodeItemType {
|
||||
return {
|
||||
@@ -663,7 +666,7 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
|
||||
value: [workflowStartNodeId, 'userChatInput']
|
||||
}
|
||||
],
|
||||
outputs: []
|
||||
outputs: ToolModule.outputs
|
||||
},
|
||||
// tool nodes
|
||||
...(datasetTool ? datasetTool.nodes : []),
|
||||
@@ -693,7 +696,8 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
|
||||
|
||||
return {
|
||||
nodes: [systemConfigTemplate(data), workflowStartTemplate(), ...workflow.nodes],
|
||||
edges: workflow.edges
|
||||
edges: workflow.edges,
|
||||
chatConfig: data.chatConfig
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -1,41 +0,0 @@
|
||||
import { GET, POST, DELETE, PUT } from '@/web/common/api/request';
|
||||
import { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/index.d';
|
||||
import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants';
|
||||
import {
|
||||
CreateOnePluginParams,
|
||||
PluginListItemType,
|
||||
UpdatePluginParams
|
||||
} from '@fastgpt/global/core/plugin/controller';
|
||||
import { PluginItemSchema } from '@fastgpt/global/core/plugin/type';
|
||||
|
||||
export const postCreatePlugin = (data: CreateOnePluginParams) =>
|
||||
POST<string>('/core/plugin/create', data);
|
||||
export const putUpdatePlugin = (data: UpdatePluginParams) => PUT('/core/plugin/update', data);
|
||||
export const getPluginPaths = (parentId?: string) =>
|
||||
GET<ParentTreePathItemType[]>('/core/plugin/paths', { parentId });
|
||||
|
||||
// http plugin
|
||||
export const getApiSchemaByUrl = (url: string) =>
|
||||
POST<Object>(
|
||||
'/core/plugin/httpPlugin/getApiSchemaByUrl',
|
||||
{ url },
|
||||
{
|
||||
timeout: 30000
|
||||
}
|
||||
);
|
||||
|
||||
/* work flow */
|
||||
export const getPlugTemplates = () => GET<FlowNodeTemplateType[]>('/core/plugin/templates');
|
||||
export const getUserPlugins = (data: { parentId?: string; type?: `${PluginTypeEnum}` }) =>
|
||||
GET<PluginListItemType[]>('/core/plugin/list', data);
|
||||
|
||||
export const getTeamPlugTemplates = (data: { parentId?: string | null; searchKey?: string }) =>
|
||||
GET<FlowNodeTemplateType[]>('/core/plugin/pluginTemplate/getTeamPluginTemplates', data);
|
||||
export const getSystemPlugTemplates = () =>
|
||||
GET<FlowNodeTemplateType[]>('/core/plugin/pluginTemplate/getSystemPluginTemplates');
|
||||
|
||||
export const getPreviewPluginModule = (id: string) =>
|
||||
GET<FlowNodeTemplateType>('/core/plugin/getPreviewNode', { id });
|
||||
export const getOnePlugin = (id: string) => GET<PluginItemSchema>('/core/plugin/detail', { id });
|
||||
export const delOnePlugin = (pluginId: string) => DELETE('/core/plugin/delete', { pluginId });
|
@@ -1,56 +0,0 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/index.d';
|
||||
import { getTeamPlugTemplates, getSystemPlugTemplates } from '../../plugin/api';
|
||||
|
||||
type State = {
|
||||
systemNodeTemplates: FlowNodeTemplateType[];
|
||||
loadSystemNodeTemplates: (init?: boolean) => Promise<FlowNodeTemplateType[]>;
|
||||
teamPluginNodeTemplates: FlowNodeTemplateType[];
|
||||
loadTeamPluginNodeTemplates: (e?: {
|
||||
parentId?: string | null;
|
||||
searchKey?: string;
|
||||
init?: boolean;
|
||||
}) => Promise<FlowNodeTemplateType[]>;
|
||||
};
|
||||
|
||||
export const useWorkflowStore = create<State>()(
|
||||
devtools(
|
||||
persist(
|
||||
immer((set, get) => ({
|
||||
systemNodeTemplates: [],
|
||||
async loadSystemNodeTemplates(init) {
|
||||
if (!init && get().systemNodeTemplates.length > 0) {
|
||||
return get().systemNodeTemplates;
|
||||
}
|
||||
const templates = await getSystemPlugTemplates();
|
||||
set((state) => {
|
||||
state.systemNodeTemplates = templates;
|
||||
});
|
||||
return templates;
|
||||
},
|
||||
teamPluginNodeTemplates: [],
|
||||
async loadTeamPluginNodeTemplates(e) {
|
||||
const { parentId = null, searchKey, init } = e || {};
|
||||
|
||||
if (!init && get().teamPluginNodeTemplates.length > 0) {
|
||||
return get().teamPluginNodeTemplates;
|
||||
}
|
||||
const templates = await getTeamPlugTemplates({
|
||||
parentId: parentId || null,
|
||||
searchKey: searchKey
|
||||
});
|
||||
set((state) => {
|
||||
state.teamPluginNodeTemplates = templates;
|
||||
});
|
||||
return templates;
|
||||
}
|
||||
})),
|
||||
{
|
||||
name: 'datasetStore',
|
||||
partialize: (state) => ({})
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
@@ -32,6 +32,7 @@ import {
|
||||
import { IfElseListItemType } from '@fastgpt/global/core/workflow/template/system/ifElse/type';
|
||||
import { VariableConditionEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant';
|
||||
import { AppChatConfigType } from '@fastgpt/global/core/app/type';
|
||||
import { cloneDeep, isEqual } from 'lodash';
|
||||
|
||||
export const nodeTemplate2FlowNode = ({
|
||||
template,
|
||||
@@ -377,3 +378,84 @@ export const updateFlowNodeVersion = (
|
||||
|
||||
return updatedNode;
|
||||
};
|
||||
|
||||
type WorkflowType = {
|
||||
nodes: StoreNodeItemType[];
|
||||
edges: StoreEdgeItemType[];
|
||||
chatConfig: AppChatConfigType;
|
||||
};
|
||||
export const compareWorkflow = (workflow1: WorkflowType, workflow2: WorkflowType) => {
|
||||
const clone1 = cloneDeep(workflow1);
|
||||
const clone2 = cloneDeep(workflow2);
|
||||
|
||||
if (!isEqual(clone1.edges, clone2.edges)) {
|
||||
console.log('Edge not equal');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
clone1.chatConfig &&
|
||||
clone2.chatConfig &&
|
||||
!isEqual(
|
||||
{
|
||||
welcomeText: clone1.chatConfig?.welcomeText || '',
|
||||
variables: clone1.chatConfig?.variables || [],
|
||||
questionGuide: clone1.chatConfig?.questionGuide || false,
|
||||
ttsConfig: clone1.chatConfig?.ttsConfig || undefined,
|
||||
whisperConfig: clone1.chatConfig?.whisperConfig || undefined,
|
||||
scheduledTriggerConfig: clone1.chatConfig?.scheduledTriggerConfig || undefined,
|
||||
chatInputGuide: clone1.chatConfig?.chatInputGuide || undefined
|
||||
},
|
||||
{
|
||||
welcomeText: clone2.chatConfig?.welcomeText || '',
|
||||
variables: clone2.chatConfig?.variables || [],
|
||||
questionGuide: clone2.chatConfig?.questionGuide || false,
|
||||
ttsConfig: clone2.chatConfig?.ttsConfig || undefined,
|
||||
whisperConfig: clone2.chatConfig?.whisperConfig || undefined,
|
||||
scheduledTriggerConfig: clone2.chatConfig?.scheduledTriggerConfig || undefined,
|
||||
chatInputGuide: clone2.chatConfig?.chatInputGuide || undefined
|
||||
}
|
||||
)
|
||||
) {
|
||||
console.log('chatConfig not equal');
|
||||
return false;
|
||||
}
|
||||
|
||||
const node1 = clone1.nodes.filter(Boolean).map((node) => ({
|
||||
flowNodeType: node.flowNodeType,
|
||||
inputs: node.inputs.map((input) => ({
|
||||
...input,
|
||||
value: input.value ?? undefined
|
||||
})),
|
||||
outputs: node.outputs.map((input) => ({
|
||||
...input,
|
||||
value: input.value ?? undefined
|
||||
})),
|
||||
name: node.name,
|
||||
intro: node.intro,
|
||||
avatar: node.avatar,
|
||||
version: node.version,
|
||||
position: node.position
|
||||
}));
|
||||
const node2 = clone2.nodes.filter(Boolean).map((node) => ({
|
||||
flowNodeType: node.flowNodeType,
|
||||
inputs: node.inputs.map((input) => ({
|
||||
...input,
|
||||
value: input.value ?? undefined
|
||||
})),
|
||||
outputs: node.outputs.map((input) => ({
|
||||
...input,
|
||||
value: input.value ?? undefined
|
||||
})),
|
||||
name: node.name,
|
||||
intro: node.intro,
|
||||
avatar: node.avatar,
|
||||
version: node.version,
|
||||
position: node.position
|
||||
}));
|
||||
|
||||
// console.log(node1);
|
||||
// console.log(node2);
|
||||
|
||||
return isEqual(node1, node2);
|
||||
};
|
||||
|
Reference in New Issue
Block a user