mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-15 15:41:05 +00:00
Feat: IfElse node support variable reference (#5025)
* if else node support reference (#5016) * if else node support reference * optimize input render * ui * fix --------- Co-authored-by: Archer <545436317@qq.com> * fix: chat * perf: download invoice * optimize ifelse node ui (#5024) * perf: ifelse node * optimize type (#5027) --------- Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
@@ -94,7 +94,7 @@ export const VariableInputItem = ({
|
||||
step={1}
|
||||
min={item.min}
|
||||
max={item.max}
|
||||
bg={'white'}
|
||||
inputFieldProps={{ bg: 'white' }}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
isInvalid={errors?.variables && Object.keys(errors.variables).includes(item.key)}
|
||||
@@ -250,18 +250,16 @@ const VariableInput = ({
|
||||
<ExternalVariableInputItem key={item.id} item={item} variablesForm={variablesForm} />
|
||||
))}
|
||||
{variableList.length === 0 && !chatStarted && (
|
||||
<Box>
|
||||
<Button
|
||||
leftIcon={<MyIcon name={'core/chat/chatFill'} w={'16px'} />}
|
||||
size={'sm'}
|
||||
maxW={'100px'}
|
||||
onClick={handleSubmitChat(() => {
|
||||
chatForm.setValue('chatStarted', true);
|
||||
})}
|
||||
>
|
||||
{t('common:core.chat.Start Chat')}
|
||||
</Button>
|
||||
</Box>
|
||||
<Button
|
||||
leftIcon={<MyIcon name={'core/chat/chatFill'} w={'16px'} />}
|
||||
size={'sm'}
|
||||
maxW={'100px'}
|
||||
onClick={handleSubmitChat(() => {
|
||||
chatForm.setValue('chatStarted', true);
|
||||
})}
|
||||
>
|
||||
{t('common:core.chat.Start Chat')}
|
||||
</Button>
|
||||
)}
|
||||
</Card>
|
||||
</Box>
|
||||
@@ -287,7 +285,6 @@ const VariableInput = ({
|
||||
size={'sm'}
|
||||
maxW={'100px'}
|
||||
onClick={handleSubmitChat(() => {
|
||||
console.log('start chat');
|
||||
chatForm.setValue('chatStarted', true);
|
||||
})}
|
||||
>
|
||||
|
@@ -198,7 +198,6 @@ const RenderPluginInput = ({
|
||||
step={1}
|
||||
min={input.min}
|
||||
max={input.max}
|
||||
bg={'myGray.50'}
|
||||
isDisabled={isDisabled}
|
||||
isInvalid={isInvalid}
|
||||
value={value}
|
||||
|
@@ -146,10 +146,10 @@ export const FormInputComponent = React.memo(function FormInputComponent({
|
||||
max={max}
|
||||
defaultValue={defaultValue}
|
||||
isDisabled={submitted}
|
||||
bg={'white'}
|
||||
register={register}
|
||||
name={label}
|
||||
isRequired={required}
|
||||
inputFieldProps={{ bg: 'white' }}
|
||||
/>
|
||||
);
|
||||
case FlowNodeInputTypeEnum.select:
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { getInvoiceRecords, readInvoiceFile } from '@/web/support/wallet/bill/invoice/api';
|
||||
import { getInvoiceRecords } from '@/web/support/wallet/bill/invoice/api';
|
||||
import MyBox from '@fastgpt/web/components/common/MyBox';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useState } from 'react';
|
||||
@@ -23,6 +23,7 @@ import dayjs from 'dayjs';
|
||||
import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/usage/tools';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import { downloadFetch } from '@/web/common/system/utils';
|
||||
|
||||
const InvoiceTable = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -138,25 +139,10 @@ function InvoiceDetailModal({
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { runAsync: handleDownloadInvoice } = useRequest2(async (id: string) => {
|
||||
const fileInfo = await readInvoiceFile(id);
|
||||
|
||||
// Blob
|
||||
const byteCharacters = atob(fileInfo.data);
|
||||
const byteNumbers = new Array(byteCharacters.length);
|
||||
for (let i = 0; i < byteCharacters.length; i++) {
|
||||
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
||||
}
|
||||
const byteArray = new Uint8Array(byteNumbers);
|
||||
const blob = new Blob([byteArray], { type: fileInfo.mimeType });
|
||||
const fileUrl = URL.createObjectURL(blob);
|
||||
|
||||
// preview
|
||||
window.open(fileUrl, '_blank');
|
||||
|
||||
// clean
|
||||
setTimeout(() => {
|
||||
URL.revokeObjectURL(fileUrl);
|
||||
}, 1000);
|
||||
await downloadFetch({
|
||||
url: `/api/proApi/support/wallet/bill/invoice/downloadFile?id=${id}`,
|
||||
filename: `${invoice.teamName}.pdf`
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
|
@@ -214,15 +214,7 @@ const RenderToolInput = ({
|
||||
);
|
||||
}
|
||||
if (paramInfo.type === 'number') {
|
||||
return (
|
||||
<MyNumberInput
|
||||
step={1}
|
||||
bg={'myGray.50'}
|
||||
isInvalid={isInvalid}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
return <MyNumberInput step={1} isInvalid={isInvalid} value={value} onChange={onChange} />;
|
||||
}
|
||||
if (paramInfo.type === 'boolean') {
|
||||
return <Switch isChecked={value} onChange={onChange} isInvalid={isInvalid} />;
|
||||
|
@@ -39,7 +39,7 @@ const NodeCQNode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
<MyIcon
|
||||
mt={1}
|
||||
mr={2}
|
||||
name={'minus'}
|
||||
name={'circleMinus'}
|
||||
w={'12px'}
|
||||
cursor={'pointer'}
|
||||
color={'myGray.600'}
|
||||
|
@@ -85,7 +85,7 @@ const NodeDatasetConcat = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
step={100}
|
||||
value={item.value}
|
||||
name={NodeInputKeyEnum.datasetMaxTokens}
|
||||
bg={'white'}
|
||||
inputFieldProps={{ bg: 'white' }}
|
||||
onChange={(e) => {
|
||||
onChangeNode({
|
||||
nodeId,
|
||||
|
@@ -1,16 +1,16 @@
|
||||
import { Box, Button, Flex } from '@chakra-ui/react';
|
||||
import { Box, Button, Flex, HStack } from '@chakra-ui/react';
|
||||
import {
|
||||
type DraggableProvided,
|
||||
type DraggableStateSnapshot
|
||||
} from '@fastgpt/web/components/common/DndDrag/index';
|
||||
import Container from '../../components/Container';
|
||||
import { MinusIcon, SmallAddIcon } from '@chakra-ui/icons';
|
||||
import { MinusIcon } from '@chakra-ui/icons';
|
||||
import { type IfElseListItemType } from '@fastgpt/global/core/workflow/template/system/ifElse/type';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { type ReferenceItemValueType } from '@fastgpt/global/core/workflow/type/io';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { ReferSelector, useReference } from '../render/RenderInput/templates/Reference';
|
||||
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { VARIABLE_NODE_ID, WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import {
|
||||
VariableConditionEnum,
|
||||
allConditionList,
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
booleanConditionList,
|
||||
numberConditionList,
|
||||
objectConditionList,
|
||||
renderNumberConditionList,
|
||||
stringConditionList
|
||||
} from '@fastgpt/global/core/workflow/template/system/ifElse/constant';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
@@ -28,9 +29,12 @@ import MyInput from '@/components/MyInput';
|
||||
import { getElseIFLabel, getHandleId } from '@fastgpt/global/core/workflow/utils';
|
||||
import { MySourceHandle } from '../render/Handle';
|
||||
import { Position, useReactFlow } from 'reactflow';
|
||||
import { getRefData } from '@/web/core/workflow/utils';
|
||||
import { getRefData, getWorkflowGlobalVariables } from '@/web/core/workflow/utils';
|
||||
import DragIcon from '@fastgpt/web/components/common/DndDrag/DragIcon';
|
||||
import { AppContext } from '@/pageComponents/app/detail/context';
|
||||
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
|
||||
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
||||
import MyIconButton from '@fastgpt/web/components/common/Icon/button';
|
||||
|
||||
const ListItem = ({
|
||||
provided,
|
||||
@@ -57,7 +61,6 @@ const ListItem = ({
|
||||
const Render = useMemo(() => {
|
||||
return (
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
position={'relative'}
|
||||
transform={snapshot.isDragging ? `scale(${getZoom()})` : ''}
|
||||
transformOrigin={'top left'}
|
||||
@@ -66,16 +69,20 @@ const ListItem = ({
|
||||
<Container w={snapshot.isDragging ? '' : 'full'} className="nodrag">
|
||||
<Flex mb={4} alignItems={'center'}>
|
||||
{ifElseList.length > 1 && <DragIcon provided={provided} />}
|
||||
<Box color={'black'} fontSize={'md'} ml={2}>
|
||||
<Box color={'myGray.900'} fontWeight={'medium'} fontSize={'md'} ml={2}>
|
||||
{getElseIFLabel(conditionIndex)}
|
||||
</Box>
|
||||
{conditionItem.list?.length > 1 && (
|
||||
<Flex
|
||||
px={'2.5'}
|
||||
ml={1.5}
|
||||
px={1}
|
||||
color={'primary.600'}
|
||||
fontWeight={'medium'}
|
||||
alignItems={'center'}
|
||||
cursor={'pointer'}
|
||||
_hover={{
|
||||
bg: 'myGray.200'
|
||||
}}
|
||||
rounded={'md'}
|
||||
onClick={() => {
|
||||
onUpdateIfElseList(
|
||||
@@ -95,7 +102,7 @@ const ListItem = ({
|
||||
<MyIcon ml={1} boxSize={5} name="change" />
|
||||
</Flex>
|
||||
)}
|
||||
<Box flex={1}></Box>
|
||||
<Box flex={1} />
|
||||
{ifElseList.length > 1 && (
|
||||
<MyIcon
|
||||
ml={2}
|
||||
@@ -103,7 +110,7 @@ const ListItem = ({
|
||||
name="delete"
|
||||
cursor={'pointer'}
|
||||
_hover={{ color: 'red.600' }}
|
||||
color={'myGray.400'}
|
||||
color={'myGray.600'}
|
||||
onClick={() => {
|
||||
onUpdateIfElseList(ifElseList.filter((_, index) => index !== conditionIndex));
|
||||
onDelEdge({
|
||||
@@ -119,102 +126,96 @@ const ListItem = ({
|
||||
return (
|
||||
<Box key={i}>
|
||||
{/* condition list */}
|
||||
<Flex gap={2} mb={2} alignItems={'center'}>
|
||||
<Flex gap={1.5} mb={2} alignItems={'center'}>
|
||||
{/* variable reference */}
|
||||
<Box minW={'250px'}>
|
||||
<VariableSelector
|
||||
nodeId={nodeId}
|
||||
variable={item.variable}
|
||||
onSelect={(e) => {
|
||||
onUpdateIfElseList(
|
||||
ifElseList.map((ifElse, index) => {
|
||||
if (index === conditionIndex) {
|
||||
return {
|
||||
...ifElse,
|
||||
list: ifElse.list.map((item, index) => {
|
||||
if (index === i) {
|
||||
return {
|
||||
...item,
|
||||
variable: e,
|
||||
condition: undefined
|
||||
};
|
||||
}
|
||||
return item;
|
||||
})
|
||||
};
|
||||
}
|
||||
return ifElse;
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
{/* condition select */}
|
||||
<Box w={'130px'} flex={1}>
|
||||
<ConditionSelect
|
||||
condition={item.condition}
|
||||
variable={item.variable}
|
||||
onSelect={(e) => {
|
||||
onUpdateIfElseList(
|
||||
ifElseList.map((ifElse, index) => {
|
||||
if (index === conditionIndex) {
|
||||
return {
|
||||
...ifElse,
|
||||
list: ifElse.list.map((item, index) => {
|
||||
if (index === i) {
|
||||
return {
|
||||
...item,
|
||||
condition: e
|
||||
};
|
||||
}
|
||||
return item;
|
||||
})
|
||||
};
|
||||
}
|
||||
return ifElse;
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
{/* value */}
|
||||
<Box w={'200px'}>
|
||||
<ConditionValueInput
|
||||
value={item.value}
|
||||
condition={item.condition}
|
||||
variable={item.variable}
|
||||
onChange={(e) => {
|
||||
onUpdateIfElseList(
|
||||
ifElseList.map((ifElse, index) => {
|
||||
<VariableSelector
|
||||
nodeId={nodeId}
|
||||
variable={item.variable}
|
||||
onSelect={(e) => {
|
||||
onUpdateIfElseList(
|
||||
ifElseList.map((ifElse, index) => {
|
||||
if (index === conditionIndex) {
|
||||
return {
|
||||
...ifElse,
|
||||
list:
|
||||
index === conditionIndex
|
||||
? ifElse.list.map((item, index) => {
|
||||
if (index === i) {
|
||||
return {
|
||||
...item,
|
||||
value: e
|
||||
};
|
||||
}
|
||||
return item;
|
||||
})
|
||||
: ifElse.list
|
||||
list: ifElse.list.map((item, index) => {
|
||||
if (index === i) {
|
||||
return {
|
||||
...item,
|
||||
variable: e,
|
||||
condition: undefined
|
||||
};
|
||||
}
|
||||
return item;
|
||||
})
|
||||
};
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
}
|
||||
return ifElse;
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{/* condition select */}
|
||||
<ConditionSelect
|
||||
condition={item.condition}
|
||||
variable={item.variable}
|
||||
onSelect={(e) => {
|
||||
onUpdateIfElseList(
|
||||
ifElseList.map((ifElse, index) => {
|
||||
if (index === conditionIndex) {
|
||||
return {
|
||||
...ifElse,
|
||||
list: ifElse.list.map((item, index) => {
|
||||
if (index === i) {
|
||||
return {
|
||||
...item,
|
||||
condition: e
|
||||
};
|
||||
}
|
||||
return item;
|
||||
})
|
||||
};
|
||||
}
|
||||
return ifElse;
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{/* value */}
|
||||
<ConditionValueInput
|
||||
value={item.value}
|
||||
valueType={item.valueType}
|
||||
condition={item.condition}
|
||||
variable={item.variable}
|
||||
nodeId={nodeId}
|
||||
updateValue={(value, valueType) => {
|
||||
onUpdateIfElseList(
|
||||
ifElseList.map((ifElse, index) => {
|
||||
return {
|
||||
...ifElse,
|
||||
list:
|
||||
index === conditionIndex
|
||||
? ifElse.list.map((item, index) => {
|
||||
if (index === i) {
|
||||
return {
|
||||
...item,
|
||||
value,
|
||||
valueType
|
||||
};
|
||||
}
|
||||
return item;
|
||||
})
|
||||
: ifElse.list
|
||||
};
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{/* delete */}
|
||||
{conditionItem.list.length > 1 && (
|
||||
<MinusIcon
|
||||
ml={2}
|
||||
boxSize={3}
|
||||
name="delete"
|
||||
cursor={'pointer'}
|
||||
_hover={{ color: 'red.600' }}
|
||||
color={'myGray.400'}
|
||||
<MyIconButton
|
||||
icon="minus"
|
||||
hoverColor={'red.600'}
|
||||
hoverBg="red.100"
|
||||
onClick={() => {
|
||||
onUpdateIfElseList(
|
||||
ifElseList.map((ifElse, index) => {
|
||||
@@ -235,30 +236,32 @@ const ListItem = ({
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onUpdateIfElseList(
|
||||
ifElseList.map((ifElse, index) => {
|
||||
if (index === conditionIndex) {
|
||||
return {
|
||||
...ifElse,
|
||||
list: ifElse.list.concat({
|
||||
variable: undefined,
|
||||
condition: undefined,
|
||||
value: undefined
|
||||
})
|
||||
};
|
||||
}
|
||||
return ifElse;
|
||||
})
|
||||
);
|
||||
}}
|
||||
variant={'link'}
|
||||
leftIcon={<SmallAddIcon />}
|
||||
color={'primary.600'}
|
||||
>
|
||||
{t('common:core.module.input.add')}
|
||||
</Button>
|
||||
<Flex>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onUpdateIfElseList(
|
||||
ifElseList.map((ifElse, index) => {
|
||||
if (index === conditionIndex) {
|
||||
return {
|
||||
...ifElse,
|
||||
list: ifElse.list.concat({
|
||||
variable: undefined,
|
||||
condition: undefined,
|
||||
value: undefined
|
||||
})
|
||||
};
|
||||
}
|
||||
return ifElse;
|
||||
})
|
||||
);
|
||||
}}
|
||||
variant={'link'}
|
||||
leftIcon={<MyIcon name={'common/addLight'} boxSize={4} mr={-1} />}
|
||||
color={'primary.700'}
|
||||
>
|
||||
{t('common:core.module.input.add')}
|
||||
</Button>
|
||||
</Flex>
|
||||
</Container>
|
||||
{!snapshot.isDragging && (
|
||||
<MySourceHandle
|
||||
@@ -324,6 +327,11 @@ const VariableSelector = ({
|
||||
value={variable}
|
||||
onSelect={onSelect}
|
||||
isArray={false}
|
||||
ButtonProps={{
|
||||
w: '14rem',
|
||||
borderColor: 'myGray.200',
|
||||
borderRadius: 'sm'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -392,7 +400,9 @@ const ConditionSelect = ({
|
||||
return (
|
||||
<MySelect
|
||||
className="nowheel"
|
||||
w={'100%'}
|
||||
w={'135px'}
|
||||
h={10}
|
||||
borderColor={'myGray.200'}
|
||||
list={filterQuiredConditionList}
|
||||
value={condition}
|
||||
onChange={onSelect}
|
||||
@@ -401,74 +411,192 @@ const ConditionSelect = ({
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
Different condition can be entered differently
|
||||
empty, notEmpty: forbid input
|
||||
boolean type: select true/false
|
||||
*/
|
||||
const ConditionValueInput = ({
|
||||
value = '',
|
||||
value,
|
||||
valueType: type,
|
||||
variable,
|
||||
condition,
|
||||
onChange
|
||||
updateValue,
|
||||
nodeId
|
||||
}: {
|
||||
value?: string;
|
||||
value?: string | ReferenceItemValueType;
|
||||
valueType?: 'input' | 'reference';
|
||||
variable?: ReferenceItemValueType;
|
||||
condition?: VariableConditionEnum;
|
||||
onChange: (e: string) => void;
|
||||
updateValue: (value: string | ReferenceItemValueType, valueType: 'input' | 'reference') => void;
|
||||
nodeId: string;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);
|
||||
const appDetail = useContextSelector(AppContext, (v) => v.appDetail);
|
||||
|
||||
const isReference = useMemo(() => type === 'reference', [type]);
|
||||
|
||||
const globalVariables = getWorkflowGlobalVariables({
|
||||
nodes: nodeList,
|
||||
chatConfig: appDetail.chatConfig
|
||||
});
|
||||
|
||||
// get value type
|
||||
const valueType = useMemo(() => {
|
||||
if (!variable) return;
|
||||
const node = nodeList.find((node) => node.nodeId === variable[0]);
|
||||
if (variable?.[0] === VARIABLE_NODE_ID) {
|
||||
return globalVariables.find((item) => item.key === variable[1])?.valueType;
|
||||
} else {
|
||||
const node = nodeList.find((node) => node.nodeId === variable?.[0]);
|
||||
const output = node?.outputs.find((item) => item.id === variable?.[1]);
|
||||
return output?.valueType;
|
||||
}
|
||||
}, [globalVariables, nodeList, variable]);
|
||||
const { referenceList } = useReference({
|
||||
nodeId,
|
||||
valueType
|
||||
});
|
||||
|
||||
if (!node) return WorkflowIOValueTypeEnum.any;
|
||||
const output = node.outputs.find((item) => item.id === variable[1]);
|
||||
const showBooleanSelect = useMemo(() => {
|
||||
return (
|
||||
valueType === WorkflowIOValueTypeEnum.boolean ||
|
||||
(valueType === WorkflowIOValueTypeEnum.arrayBoolean &&
|
||||
condition &&
|
||||
!renderNumberConditionList.has(condition))
|
||||
);
|
||||
}, [condition, valueType]);
|
||||
const showNumberInput = useMemo(() => {
|
||||
return (
|
||||
valueType === WorkflowIOValueTypeEnum.number ||
|
||||
valueType === WorkflowIOValueTypeEnum.arrayNumber ||
|
||||
(valueType?.includes('array') && condition && renderNumberConditionList.has(condition))
|
||||
);
|
||||
}, [condition, valueType]);
|
||||
|
||||
if (!output) return WorkflowIOValueTypeEnum.any;
|
||||
return output.valueType;
|
||||
}, [nodeList, variable]);
|
||||
|
||||
const Render = useMemo(() => {
|
||||
if (valueType === WorkflowIOValueTypeEnum.boolean) {
|
||||
const RenderInput = useMemo(() => {
|
||||
if (showBooleanSelect) {
|
||||
return (
|
||||
<MySelect
|
||||
list={[
|
||||
{ label: 'True', value: 'true' },
|
||||
{ label: 'False', value: 'false' }
|
||||
]}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
onChange={(e) => updateValue(e, 'input')}
|
||||
value={value as string}
|
||||
placeholder={t('workflow:ifelse.Select value')}
|
||||
isDisabled={
|
||||
condition === VariableConditionEnum.isEmpty ||
|
||||
condition === VariableConditionEnum.isNotEmpty
|
||||
}
|
||||
borderLeftRadius={0}
|
||||
h={10}
|
||||
borderColor={'myGray.200'}
|
||||
/>
|
||||
);
|
||||
} else if (showNumberInput) {
|
||||
return (
|
||||
<MyNumberInput
|
||||
step={1}
|
||||
inputFieldProps={{
|
||||
bg: 'white',
|
||||
borderLeftRadius: 'none'
|
||||
}}
|
||||
value={Number(value as string)}
|
||||
onChange={(e) => updateValue(String(e), 'input')}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<MyInput
|
||||
value={value}
|
||||
value={value as string}
|
||||
placeholder={
|
||||
condition === VariableConditionEnum.reg
|
||||
? '/^((+|00)86)?1[3-9]d{9}$/'
|
||||
: t('workflow:ifelse.Input value')
|
||||
}
|
||||
w={'100%'}
|
||||
w={'full'}
|
||||
h={'full'}
|
||||
bg={'white'}
|
||||
isDisabled={
|
||||
condition === VariableConditionEnum.isEmpty ||
|
||||
condition === VariableConditionEnum.isNotEmpty
|
||||
}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
borderLeftRadius={0}
|
||||
onChange={(e) => updateValue(e.target.value, 'input')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}, [condition, onChange, value, valueType, t]);
|
||||
}, [showBooleanSelect, showNumberInput, value, t, condition, updateValue]);
|
||||
|
||||
return Render;
|
||||
const RenderReference = useMemo(() => {
|
||||
return (
|
||||
<ReferSelector
|
||||
placeholder={t('common:select_reference_variable')}
|
||||
list={referenceList}
|
||||
value={isReference ? (value as ReferenceItemValueType) : undefined}
|
||||
onSelect={(e) => {
|
||||
updateValue(e as ReferenceItemValueType, 'reference');
|
||||
}}
|
||||
isArray={false}
|
||||
ButtonProps={{
|
||||
borderRadius: 'sm',
|
||||
borderLeftRadius: 'none',
|
||||
borderColor: 'myGray.200',
|
||||
w: '100%'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}, [t, referenceList, isReference, value, updateValue]);
|
||||
|
||||
const isDisabled =
|
||||
condition === VariableConditionEnum.isEmpty || condition === VariableConditionEnum.isNotEmpty;
|
||||
|
||||
return (
|
||||
<Flex position="relative">
|
||||
<Flex>
|
||||
<MyTooltip
|
||||
label={
|
||||
isReference
|
||||
? t('workflow:click_to_change_reference')
|
||||
: t('workflow:click_to_change_value')
|
||||
}
|
||||
>
|
||||
<HStack
|
||||
w={'4rem'}
|
||||
h={10}
|
||||
border={'1px solid'}
|
||||
borderRight={'none'}
|
||||
borderColor={'myGray.200'}
|
||||
borderLeftRadius={'sm'}
|
||||
justifyContent={'center'}
|
||||
bg={'white'}
|
||||
px={2}
|
||||
spacing={2}
|
||||
cursor={'pointer'}
|
||||
_hover={{
|
||||
bg: 'myGray.50'
|
||||
}}
|
||||
onClick={() => {
|
||||
if (isDisabled) return;
|
||||
|
||||
if (isReference) {
|
||||
updateValue('', 'input');
|
||||
} else {
|
||||
updateValue(['', undefined], 'reference');
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isReference ? (
|
||||
<MyIcon name={'core/workflow/inputType/reference'} w={4} color={'primary.600'} />
|
||||
) : (
|
||||
<MyIcon name={'core/app/variable/input'} w={4} color={'primary.600'} />
|
||||
)}
|
||||
<MyIcon name={'common/lineChange'} w={'14px'} color={'myGray.500'} />
|
||||
</HStack>
|
||||
</MyTooltip>
|
||||
<Box w={'14rem'}>{isReference ? RenderReference : RenderInput}</Box>
|
||||
</Flex>
|
||||
|
||||
{isDisabled && (
|
||||
<Box
|
||||
position="absolute"
|
||||
top={0}
|
||||
left={0}
|
||||
right={0}
|
||||
bottom={0}
|
||||
bg="whiteAlpha.700"
|
||||
zIndex={1}
|
||||
borderRadius="sm"
|
||||
cursor="not-allowed"
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@@ -3,7 +3,7 @@ import NodeCard from '../render/NodeCard';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { Box, Button, Flex } from '@chakra-ui/react';
|
||||
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { type NodeProps, Position, useViewport } from 'reactflow';
|
||||
import { type NodeProps, Position } from 'reactflow';
|
||||
import { type FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node';
|
||||
import { type IfElseListItemType } from '@fastgpt/global/core/workflow/template/system/ifElse/type';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
@@ -14,11 +14,11 @@ import { MySourceHandle } from '../render/Handle';
|
||||
import { getHandleId } from '@fastgpt/global/core/workflow/utils';
|
||||
import ListItem from './ListItem';
|
||||
import { IfElseResultEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
||||
const NodeIfElse = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
const { t } = useTranslation();
|
||||
const { nodeId, inputs = [] } = data;
|
||||
const { zoom } = useViewport();
|
||||
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
|
||||
const elseHandleId = getHandleId(nodeId, 'source', IfElseResultEnum.ELSE);
|
||||
|
||||
@@ -108,6 +108,7 @@ const NodeIfElse = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
<Button
|
||||
variant={'whiteBase'}
|
||||
w={'full'}
|
||||
leftIcon={<MyIcon name={'common/addLight'} boxSize={4} mr={-1} />}
|
||||
onClick={() => {
|
||||
const ifElseListInput = inputs.find(
|
||||
(input) => input.key === NodeInputKeyEnum.ifElseList
|
||||
|
@@ -157,7 +157,7 @@ const OptionItem = ({
|
||||
<MyTooltip label={t('common:Delete')}>
|
||||
<MyIcon
|
||||
mt={0.5}
|
||||
name={'minus'}
|
||||
name={'circleMinus'}
|
||||
w={'0.8rem'}
|
||||
cursor={'pointer'}
|
||||
color={'myGray.600'}
|
||||
|
@@ -249,7 +249,7 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps<FlowNodeItemType>) =>
|
||||
if (valueType === WorkflowIOValueTypeEnum.number) {
|
||||
return (
|
||||
<MyNumberInput
|
||||
bg={'white'}
|
||||
inputFieldProps={{ bg: 'white' }}
|
||||
value={Number(inputValue) || 0}
|
||||
onChange={(e) => onUpdateNewValue(String(e || 0))}
|
||||
/>
|
||||
|
@@ -13,7 +13,7 @@ const NumberInputRender = ({ item, nodeId }: RenderInputProps) => {
|
||||
value={item.value}
|
||||
min={item.min}
|
||||
max={item.max}
|
||||
bg={'white'}
|
||||
inputFieldProps={{ bg: 'white' }}
|
||||
rounded={'md'}
|
||||
onChange={(e) => {
|
||||
onChangeNode({
|
||||
|
@@ -47,7 +47,7 @@ type CommonSelectProps = {
|
||||
}[];
|
||||
}[];
|
||||
popDirection?: 'top' | 'bottom';
|
||||
styles?: ButtonProps;
|
||||
ButtonProps?: ButtonProps;
|
||||
};
|
||||
type SelectProps<T extends boolean> = CommonSelectProps & {
|
||||
isArray?: T;
|
||||
@@ -87,7 +87,7 @@ export const useReference = ({
|
||||
return {
|
||||
label: (
|
||||
<Flex alignItems={'center'}>
|
||||
<Avatar src={node.avatar} w={isArray ? '1rem' : '1.25rem'} borderRadius={'xs'} />
|
||||
<Avatar src={node.avatar} w={isArray ? '1rem' : '1.05rem'} borderRadius={'xs'} />
|
||||
<Box ml={1}>{t(node.name as any)}</Box>
|
||||
</Flex>
|
||||
),
|
||||
@@ -168,7 +168,8 @@ const SingleReferenceSelector = ({
|
||||
value,
|
||||
list = [],
|
||||
onSelect,
|
||||
popDirection
|
||||
popDirection,
|
||||
ButtonProps
|
||||
}: SelectProps<false>) => {
|
||||
const getSelectValue = useCallback(
|
||||
(value: ReferenceValueType) => {
|
||||
@@ -196,12 +197,10 @@ const SingleReferenceSelector = ({
|
||||
<MultipleRowSelect
|
||||
label={
|
||||
isValidSelect ? (
|
||||
<Flex gap={2} alignItems={'center'} fontSize={'sm'}>
|
||||
<Flex py={1} pl={1} alignItems={'center'}>
|
||||
{nodeName}
|
||||
<MyIcon name={'common/rightArrowLight'} mx={1} w={'12px'} color={'myGray.500'} />
|
||||
{outputName}
|
||||
</Flex>
|
||||
<Flex py={1} pl={1} alignItems={'center'} fontSize={'sm'}>
|
||||
{nodeName}
|
||||
<MyIcon name={'common/rightArrowLight'} mx={0.5} w={'12px'} color={'myGray.500'} />
|
||||
{outputName}
|
||||
</Flex>
|
||||
) : (
|
||||
<Box fontSize={'sm'} color={'myGray.400'}>
|
||||
@@ -213,9 +212,10 @@ const SingleReferenceSelector = ({
|
||||
list={list}
|
||||
onSelect={onSelect as any}
|
||||
popDirection={popDirection}
|
||||
ButtonProps={ButtonProps}
|
||||
/>
|
||||
);
|
||||
}, [getSelectValue, list, onSelect, placeholder, popDirection, value]);
|
||||
}, [ButtonProps, getSelectValue, list, onSelect, placeholder, popDirection, value]);
|
||||
|
||||
return ItemSelector;
|
||||
};
|
||||
@@ -226,8 +226,6 @@ const MultipleReferenceSelector = ({
|
||||
onSelect,
|
||||
popDirection
|
||||
}: SelectProps<true>) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const getSelectValue = useCallback(
|
||||
(value: ReferenceValueType) => {
|
||||
if (!value) return [];
|
||||
|
@@ -269,7 +269,7 @@ const CollectionChunkForm = ({ form }: { form: UseFormReturn<CollectionChunkForm
|
||||
<Box flex={'1 0 0'}>
|
||||
<MyNumberInput
|
||||
h={'34px'}
|
||||
bg={'white'}
|
||||
inputFieldProps={{ bg: 'white' }}
|
||||
min={100}
|
||||
max={100000}
|
||||
register={register}
|
||||
|
@@ -20,6 +20,3 @@ export const submitInvoice = (data: InvoiceType) =>
|
||||
|
||||
export const getInvoiceRecords = (data: PaginationProps) =>
|
||||
POST<PaginationResponse<InvoiceSchemaType>>(`/proApi/support/wallet/bill/invoice/records`, data);
|
||||
|
||||
export const readInvoiceFile = (id: string) =>
|
||||
GET<InvoiceFileInfo>(`/proApi/support/wallet/bill/invoice/file/read`, { id });
|
||||
|
Reference in New Issue
Block a user