Fix 4.8 node (#1370)

* perf: runtime props

* fix: Plugin run faied in debug mode

* perf: variable update

* fix: ts

* perf: variable ui
This commit is contained in:
Archer
2024-05-06 17:13:50 +08:00
committed by GitHub
parent 5bb9c550f6
commit eef609a063
37 changed files with 398 additions and 249 deletions

View File

@@ -160,7 +160,7 @@ const ChatBox = (
/* variable */
const filterVariableModules = useMemo(
() => variableModules.filter((item) => item.type !== VariableInputEnum.external),
() => variableModules.filter((item) => item.type !== VariableInputEnum.custom),
[variableModules]
);

View File

@@ -173,7 +173,7 @@ const VariableEdit = ({
maxW={['90vw', '500px']}
>
<ModalBody>
{variableType !== VariableInputEnum.external && (
{variableType !== VariableInputEnum.custom && (
<Flex alignItems={'center'}>
<Box w={'70px'}>{t('common.Require Input')}</Box>
<Switch {...registerEdit('variable.required')} />
@@ -197,7 +197,7 @@ const VariableEdit = ({
</Flex>
<Box mt={5} mb={2}>
{t('core.module.Field Type')}
{t('core.workflow.Variable.Variable type')}
</Box>
<MyRadio
gridGap={4}

View File

@@ -31,13 +31,13 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { ReferenceValueProps } from '@fastgpt/global/core/workflow/type/io';
import { ReferSelector, useReference } from './render/RenderInput/templates/Reference';
import { getWorkflowGlobalVariables } from '@/web/core/workflow/utils';
import { isReferenceValue } from '@fastgpt/global/core/workflow/utils';
const NodeVariableUpdate = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
const { inputs = [], nodeId } = data;
const { t } = useTranslation();
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
const nodes = useContextSelector(WorkflowContext, (v) => v.nodes);
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);
const updateList = useMemo(
@@ -65,175 +65,201 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps<FlowNodeItemType>) =>
[inputs, nodeId, onChangeNode]
);
const menuList = [
{
renderType: FlowNodeInputTypeEnum.input,
icon: FlowNodeInputMap[FlowNodeInputTypeEnum.input].icon,
label: t('core.workflow.inputType.Manual input')
},
{
renderType: FlowNodeInputTypeEnum.reference,
icon: FlowNodeInputMap[FlowNodeInputTypeEnum.reference].icon,
label: t('core.workflow.inputType.Reference')
}
];
const Render = useMemo(() => {
const menuList = [
{
renderType: FlowNodeInputTypeEnum.input,
icon: FlowNodeInputMap[FlowNodeInputTypeEnum.input].icon,
label: t('core.workflow.inputType.Manual input')
},
{
renderType: FlowNodeInputTypeEnum.reference,
icon: FlowNodeInputMap[FlowNodeInputTypeEnum.reference].icon,
label: t('core.workflow.inputType.Reference')
}
];
return (
<NodeCard selected={selected} maxW={'1000px'} {...data}>
<Box px={4} pb={4}>
return (
<>
{updateList.map((updateItem, index) => {
const type = (() => {
const valueType = (() => {
const variable = updateItem.variable;
const variableNodeId = variable?.[0];
const variableNode = nodes.find((node) => node.id === variableNodeId);
const variableNode = nodeList.find((node) => node.nodeId === variableNodeId);
const systemVariables = getWorkflowGlobalVariables(nodeList, t);
const variableInput = !variableNode
? systemVariables.find((item) => item.key === variable?.[1])
: variableNode?.data.outputs.find((output) => output.id === variable?.[1]);
if (!variableInput) return 'any';
: variableNode.outputs.find((output) => output.id === variable?.[1]);
if (!variableInput) return WorkflowIOValueTypeEnum.any;
return variableInput.valueType;
})();
const renderTypeData = menuList.find((item) => item.renderType === updateItem.renderType);
const handleUpdate = (newValue: ReferenceValueProps | string) => {
if (Array.isArray(newValue)) {
if (isReferenceValue(newValue)) {
onUpdateList(
updateList.map((update, i) =>
i === index ? { ...update, value: newValue } : update
i === index ? { ...update, value: newValue as ReferenceValueProps } : update
)
);
} else {
onUpdateList(
updateList.map((update, i) =>
i === index ? { ...update, value: ['', newValue] } : update
i === index ? { ...update, value: ['', newValue as string] } : update
)
);
}
};
return (
<Flex key={index}>
<Container mt={4} w={'full'}>
<Flex alignItems={'center'}>
<Flex w={'60px'}>{t('core.workflow.variable')}</Flex>
<Reference
nodeId={nodeId}
variable={updateItem.variable}
onSelect={(value) => {
onUpdateList(
updateList.map((update, i) => {
if (i === index) {
return {
...update,
variable: value
};
}
return update;
})
);
<Container key={index} mt={4} w={'full'} mx={0}>
<Flex alignItems={'center'}>
<Flex w={'60px'}>{t('core.workflow.variable')}</Flex>
<Reference
nodeId={nodeId}
variable={updateItem.variable}
onSelect={(value) => {
onUpdateList(
updateList.map((update, i) => {
if (i === index) {
return {
...update,
value: ['', ''],
valueType,
variable: value
};
}
return update;
})
);
}}
/>
<Box flex={1} />
{updateList.length > 1 && (
<MyIcon
className="delete"
name={'delete'}
w={'14px'}
color={'myGray.600'}
cursor={'pointer'}
_hover={{ color: 'red.500' }}
position={'absolute'}
top={3}
right={3}
onClick={() => {
onUpdateList(updateList.filter((_, i) => i !== index));
}}
/>
<Box flex={1} />
{updateList.length > 1 && (
<MyIcon
className="delete"
name={'delete'}
w={'14px'}
color={'myGray.600'}
cursor={'pointer'}
ml={2}
_hover={{ color: 'red.500' }}
)}
</Flex>
<Flex mt={2} w={'full'} alignItems={'center'} className="nodrag">
<Flex w={'60px'}>
<Box>{t('core.workflow.value')}</Box>
<MyTooltip
label={
menuList.find((item) => item.renderType === updateItem.renderType)?.label
}
>
<Button
size={'xs'}
bg={'white'}
borderRadius={'xs'}
mx={2}
onClick={() => {
onUpdateList(updateList.filter((_, i) => i !== index));
onUpdateList(
updateList.map((update, i) => {
if (i === index) {
return {
...update,
value: ['', ''],
renderType:
updateItem.renderType === FlowNodeInputTypeEnum.input
? FlowNodeInputTypeEnum.reference
: FlowNodeInputTypeEnum.input
};
}
return update;
})
);
}}
/>
)}
</Flex>
<Flex mt={2} w={'full'} alignItems={'center'} className="nodrag">
<Flex w={'60px'}>
<Box>{t('core.workflow.value')}</Box>
<MyTooltip
label={
menuList.find((item) => item.renderType === updateItem.renderType)?.label
}
>
<Button
size={'xs'}
bg={'white'}
borderRadius={'xs'}
mx={2}
onClick={() => {
onUpdateList(
updateList.map((update, i) => {
if (i === index) {
return {
...update,
value: ['', ''],
renderType:
updateItem.renderType === FlowNodeInputTypeEnum.input
? FlowNodeInputTypeEnum.reference
: FlowNodeInputTypeEnum.input
};
}
return update;
})
);
}}
>
<MyIcon name={renderTypeData?.icon as any} w={'14px'} />
</Button>
</MyTooltip>
</Flex>
{updateItem.renderType === FlowNodeInputTypeEnum.reference ? (
<Reference
nodeId={nodeId}
variable={updateItem.value}
onSelect={handleUpdate}
/>
) : (
<>
{type === 'string' && (
<Textarea
<MyIcon name={renderTypeData?.icon as any} w={'14px'} />
</Button>
</MyTooltip>
</Flex>
{/* Render input components */}
{(() => {
if (updateItem.renderType === FlowNodeInputTypeEnum.reference) {
return (
<Reference
nodeId={nodeId}
variable={updateItem.value}
valueType={valueType}
onSelect={handleUpdate}
/>
);
}
if (valueType === WorkflowIOValueTypeEnum.string) {
return (
<Textarea
bg="white"
value={updateItem.value?.[1] || ''}
w="300px"
onChange={(e) => handleUpdate(e.target.value)}
/>
);
}
if (valueType === WorkflowIOValueTypeEnum.number) {
return (
<NumberInput value={Number(updateItem.value?.[1]) || 0}>
<NumberInputField
bg="white"
value={updateItem.value?.[1] || ''}
w="300px"
onChange={(e) => handleUpdate(e.target.value)}
/>
)}
{type === 'number' && (
<NumberInput value={Number(updateItem.value?.[1]) || 0}>
<NumberInputField
bg="white"
onChange={(e) => handleUpdate(e.target.value)}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
)}
{type === 'boolean' && (
<Switch
size="lg"
defaultChecked={updateItem.value?.[1] === 'true'}
onChange={(e) => handleUpdate(String(e.target.checked))}
/>
)}
{type !== 'string' && type !== 'number' && type !== 'boolean' && (
<JsonEditor
bg="white"
resize
w="300px"
value={updateItem.value?.[1] || ''}
onChange={(e) => handleUpdate(e)}
/>
)}
</>
)}
</Flex>
</Container>
</Flex>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
);
}
if (valueType === WorkflowIOValueTypeEnum.boolean) {
return (
<Switch
size="lg"
defaultChecked={updateItem.value?.[1] === 'true'}
onChange={(e) => handleUpdate(String(e.target.checked))}
/>
);
}
return (
<JsonEditor
bg="white"
resize
w="300px"
value={String(updateItem.value?.[1] || '')}
onChange={(e) => {
handleUpdate(e);
}}
/>
);
})()}
</Flex>
</Container>
);
})}
</>
);
}, [nodeId, nodeList, onUpdateList, t, updateList]);
return (
<NodeCard selected={selected} maxW={'1000px'} {...data}>
<Box px={4} pb={4}>
{Render}
<Flex className="nodrag" cursor={'default'} alignItems={'center'} position={'relative'}>
<Button
variant={'whiteBase'}
@@ -264,17 +290,19 @@ export default React.memo(NodeVariableUpdate);
const Reference = ({
nodeId,
variable,
valueType,
onSelect
}: {
nodeId: string;
variable?: ReferenceValueProps;
valueType?: WorkflowIOValueTypeEnum;
onSelect: (e: ReferenceValueProps) => void;
}) => {
const { t } = useTranslation();
const { referenceList, formatValue } = useReference({
nodeId,
valueType: WorkflowIOValueTypeEnum.any,
valueType,
value: variable
});

View File

@@ -90,7 +90,7 @@ export default React.memo(Reference);
export const useReference = ({
nodeId,
valueType,
valueType = WorkflowIOValueTypeEnum.any,
value
}: {
nodeId: string;

View File

@@ -36,7 +36,6 @@ import { createContext } from 'use-context-selector';
import { defaultRunningStatus } from './constants';
import { checkNodeRunStatus } from '@fastgpt/global/core/workflow/runtime/utils';
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
import { AppVersionSchemaType } from '@fastgpt/global/core/app/version';
type OnChange<ChangesType> = (changes: ChangesType[]) => void;
@@ -256,7 +255,11 @@ const WorkflowContextProvider = ({
const [nodes = [], setNodes, onNodesChange] = useNodesState<FlowNodeItemType>([]);
const [hoverNodeId, setHoverNodeId] = useState<string>();
const nodeList = useCreation(() => nodes.map((node) => node.data), [nodes]);
const nodeListString = JSON.stringify(nodes.map((node) => node.data));
const nodeList = useMemo(
() => JSON.parse(nodeListString) as FlowNodeItemType[],
[nodeListString]
);
const hasToolNode = useMemo(() => {
return !!nodes.find((node) => node.data.flowNodeType === FlowNodeTypeEnum.tools);