mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-29 01:40:51 +00:00
4.8.1 test-fix (#1561)
This commit is contained in:
@@ -30,7 +30,7 @@ export default function InputGuideBox({
|
||||
return await queryChatInputGuideList(
|
||||
{
|
||||
appId,
|
||||
searchKey: text
|
||||
searchKey: text.slice(0, 50)
|
||||
},
|
||||
chatInputGuide.customUrl ? chatInputGuide.customUrl : undefined
|
||||
);
|
||||
|
@@ -9,6 +9,7 @@ import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { ChatBoxInputFormType } from '../type.d';
|
||||
import { useRefresh } from '@fastgpt/web/hooks/useRefresh';
|
||||
|
||||
const VariableInput = ({
|
||||
appAvatar,
|
||||
@@ -25,6 +26,7 @@ const VariableInput = ({
|
||||
const { register, setValue, handleSubmit: handleSubmitChat, watch } = chatForm;
|
||||
const variables = watch('variables');
|
||||
const chatStarted = watch('chatStarted');
|
||||
const { refresh } = useRefresh();
|
||||
|
||||
return (
|
||||
<Box py={3}>
|
||||
@@ -86,6 +88,7 @@ const VariableInput = ({
|
||||
})}
|
||||
value={variables[item.key]}
|
||||
onchange={(e) => {
|
||||
refresh();
|
||||
setValue(`variables.${item.key}`, e);
|
||||
}}
|
||||
/>
|
||||
|
@@ -21,7 +21,6 @@ import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { Box, Flex, Checkbox } from '@chakra-ui/react';
|
||||
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
|
||||
import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt';
|
||||
import { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/index.d';
|
||||
import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||
import { useForm } from 'react-hook-form';
|
||||
|
@@ -37,6 +37,7 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import { useRequest } from 'ahooks';
|
||||
import HighlightText from '@fastgpt/web/components/common/String/HighlightText';
|
||||
import { defaultChatInputGuideConfig } from '@fastgpt/global/core/app/constants';
|
||||
import ChatFunctionTip from './Tip';
|
||||
|
||||
const csvTemplate = `"第一列内容"
|
||||
"只会将第一列内容导入,其余列会被忽略"
|
||||
@@ -86,7 +87,7 @@ const InputGuideConfig = ({
|
||||
<MyIcon name={'core/app/inputGuides'} mr={2} w={'20px'} />
|
||||
<HStack>
|
||||
<Box>{chatT('Input guide')}</Box>
|
||||
<QuestionTip label={chatT('Input guide tip')} />
|
||||
<ChatFunctionTip type={'inputGuide'} />
|
||||
</HStack>
|
||||
<Box flex={1} />
|
||||
<MyTooltip label={chatT('Config input guide')}>
|
@@ -1,9 +1,8 @@
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { Box, Flex, Switch, type SwitchProps } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import ChatFunctionTip from './Tip';
|
||||
|
||||
// question generator switch
|
||||
const QGSwitch = (props: SwitchProps) => {
|
||||
@@ -12,9 +11,7 @@ const QGSwitch = (props: SwitchProps) => {
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'core/chat/QGFill'} mr={2} w={'20px'} />
|
||||
<Box fontWeight={'medium'}>{t('core.app.Question Guide')}</Box>
|
||||
<MyTooltip label={t('core.app.Question Guide Tip')} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
<ChatFunctionTip type={'nextQuestion'} />
|
||||
<Box flex={1} />
|
||||
<Switch {...props} />
|
||||
</Flex>
|
||||
|
@@ -8,7 +8,6 @@ import { AppScheduledTriggerConfigType } from '@fastgpt/global/core/app/type';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import dynamic from 'next/dynamic';
|
||||
import type { MultipleSelectProps } from '@fastgpt/web/components/common/MySelect/type.d';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { cronParser2Fields } from '@fastgpt/global/common/string/time';
|
||||
import TimezoneSelect from '@fastgpt/web/components/common/MySelect/TimezoneSelect';
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { Box, Button, Flex, ModalBody, useDisclosure, Image } from '@chakra-ui/react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
@@ -12,6 +11,7 @@ import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import MySlider from '@/components/Slider';
|
||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||
import { defaultTTSConfig } from '@fastgpt/global/core/app/constants';
|
||||
import ChatFunctionTip from './Tip';
|
||||
|
||||
const TTSSelect = ({
|
||||
value = defaultTTSConfig,
|
||||
@@ -82,9 +82,7 @@ const TTSSelect = ({
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'core/app/simpleMode/tts'} mr={2} w={'20px'} />
|
||||
<Box fontWeight={'medium'}>{t('core.app.TTS')}</Box>
|
||||
<MyTooltip label={t('core.app.TTS Tip')} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
<ChatFunctionTip type={'tts'} />
|
||||
<Box flex={1} />
|
||||
<MyTooltip label={t('core.app.Select TTS')}>
|
||||
<Button
|
||||
|
75
projects/app/src/components/core/app/Tip.tsx
Normal file
75
projects/app/src/components/core/app/Tip.tsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import { useI18n } from '@/web/context/I18n';
|
||||
import { Box, Flex, Image } from '@chakra-ui/react';
|
||||
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import React, { useRef } from 'react';
|
||||
|
||||
enum FnTypeEnum {
|
||||
inputGuide = 'inputGuide',
|
||||
nextQuestion = 'nextQuestion',
|
||||
tts = 'tts',
|
||||
variable = 'variable',
|
||||
welcome = 'welcome'
|
||||
}
|
||||
|
||||
const ChatFunctionTip = ({ type }: { type: `${FnTypeEnum}` }) => {
|
||||
const { t } = useTranslation();
|
||||
const { chatT } = useI18n();
|
||||
|
||||
const map = useRef({
|
||||
[FnTypeEnum.inputGuide]: {
|
||||
icon: '/imgs/app/inputGuide-icon.svg',
|
||||
title: chatT('Input guide'),
|
||||
desc: chatT('Input guide tip'),
|
||||
imgUrl: '/imgs/app/inputGuide.svg'
|
||||
},
|
||||
[FnTypeEnum.nextQuestion]: {
|
||||
icon: '/imgs/app/nextQuestion-icon.svg',
|
||||
title: t('core.app.Question Guide'),
|
||||
desc: t('core.app.Question Guide Tip'),
|
||||
imgUrl: '/imgs/app/nextQuestion.svg'
|
||||
},
|
||||
[FnTypeEnum.tts]: {
|
||||
icon: '/imgs/app/tts-icon.svg',
|
||||
title: t('core.app.TTS'),
|
||||
desc: t('core.app.TTS Tip'),
|
||||
imgUrl: '/imgs/app/tts.svg'
|
||||
},
|
||||
[FnTypeEnum.variable]: {
|
||||
icon: '/imgs/app/variable-icon.svg',
|
||||
title: t('core.module.Variable'),
|
||||
desc: t('core.app.tip.variableTip'),
|
||||
imgUrl: '/imgs/app/variable.svg'
|
||||
},
|
||||
[FnTypeEnum.welcome]: {
|
||||
icon: '/imgs/app/welcome-icon.svg',
|
||||
title: t('core.app.Welcome Text'),
|
||||
desc: t('core.app.tip.welcomeTextTip'),
|
||||
imgUrl: '/imgs/app/welcome.svg'
|
||||
}
|
||||
});
|
||||
const data = map.current[type];
|
||||
|
||||
return (
|
||||
<QuestionTip
|
||||
maxW={'420px'}
|
||||
ml={1}
|
||||
label={
|
||||
<Box>
|
||||
<Flex>
|
||||
<Image src={data.icon} w={'36px'} alt={''} />
|
||||
<Box ml={3}>
|
||||
<Box fontWeight="bold">{data.title}</Box>
|
||||
<Box fontSize={'xs'} color={'myGray.500'}>
|
||||
{data.desc}
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Image src={data.imgUrl} w={'100%'} minH={['auto', '200px']} mt={2} alt={''} />
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChatFunctionTip;
|
@@ -32,11 +32,11 @@ import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { variableTip } from '@fastgpt/global/core/workflow/template/tip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import MyRadio from '@/components/common/MyRadio';
|
||||
import { formatEditorVariablePickerIcon } from '@fastgpt/global/core/workflow/utils';
|
||||
import ChatFunctionTip from './Tip';
|
||||
|
||||
const VariableEdit = ({
|
||||
variables = [],
|
||||
@@ -96,12 +96,11 @@ const VariableEdit = ({
|
||||
<Box>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'core/app/simpleMode/variable'} w={'20px'} />
|
||||
<Box ml={2} flex={1} fontWeight={'medium'}>
|
||||
<Box ml={2} fontWeight={'medium'}>
|
||||
{t('core.module.Variable')}
|
||||
<MyTooltip label={t(variableTip)} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
</Box>
|
||||
<ChatFunctionTip type={'variable'} />
|
||||
<Box flex={1} />
|
||||
<Button
|
||||
variant={'transparentBase'}
|
||||
leftIcon={<SmallAddIcon />}
|
||||
|
29
projects/app/src/components/core/app/WelcomeTextConfig.tsx
Normal file
29
projects/app/src/components/core/app/WelcomeTextConfig.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Box, Flex, TextareaProps } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import ChatFunctionTip from './Tip';
|
||||
import MyTextarea from '@/components/common/Textarea/MyTextarea';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
const WelcomeTextConfig = (props: TextareaProps) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'core/app/simpleMode/chat'} w={'20px'} />
|
||||
<Box ml={2}>{t('core.app.Welcome Text')}</Box>
|
||||
<ChatFunctionTip type={'welcome'} />
|
||||
</Flex>
|
||||
<MyTextarea
|
||||
mt={2}
|
||||
bg={'myWhite.400'}
|
||||
rows={6}
|
||||
fontSize={'sm'}
|
||||
placeholder={t('core.app.tip.welcomeTextTip')}
|
||||
{...props}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WelcomeTextConfig;
|
@@ -19,26 +19,26 @@ const scoreTheme: Record<
|
||||
color: string;
|
||||
bg: string;
|
||||
borderColor: string;
|
||||
colorSchema: string;
|
||||
colorScheme: string;
|
||||
}
|
||||
> = {
|
||||
'0': {
|
||||
color: '#6F5DD7',
|
||||
bg: '#F0EEFF',
|
||||
borderColor: '#D3CAFF',
|
||||
colorSchema: 'purple'
|
||||
colorScheme: 'purple'
|
||||
},
|
||||
'1': {
|
||||
color: '#9E53C1',
|
||||
bg: '#FAF1FF',
|
||||
borderColor: '#ECF',
|
||||
colorSchema: 'pink'
|
||||
colorScheme: 'pink'
|
||||
},
|
||||
'2': {
|
||||
color: '#0884DD',
|
||||
bg: '#F0FBFF',
|
||||
borderColor: '#BCE7FF',
|
||||
colorSchema: 'blue'
|
||||
colorScheme: 'blue'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -184,7 +184,7 @@ const QuoteItem = ({
|
||||
size="sm"
|
||||
borderRadius={'20px'}
|
||||
{...(scoreTheme[i] && {
|
||||
colorScheme: scoreTheme[i].colorSchema
|
||||
colorScheme: scoreTheme[i].colorScheme
|
||||
})}
|
||||
bg="#E8EBF0"
|
||||
/>
|
||||
|
@@ -165,84 +165,82 @@ export const useDebug = () => {
|
||||
maxW={['90vw', '35vw']}
|
||||
px={0}
|
||||
>
|
||||
<Flex flexDirection={'column'} h={'100%'} overflowY={'auto'}>
|
||||
<Box flex={'1 0 0'} overflow={'auto'} px={6}>
|
||||
{renderInputs.map((input) => {
|
||||
const required = input.required || false;
|
||||
console.log(input.valueType);
|
||||
const RenderInput = (() => {
|
||||
if (input.valueType === WorkflowIOValueTypeEnum.string) {
|
||||
return (
|
||||
<Textarea
|
||||
<Box flex={'1 0 0'} overflow={'auto'} px={6}>
|
||||
{renderInputs.map((input) => {
|
||||
const required = input.required || false;
|
||||
console.log(input.valueType);
|
||||
const RenderInput = (() => {
|
||||
if (input.valueType === WorkflowIOValueTypeEnum.string) {
|
||||
return (
|
||||
<Textarea
|
||||
{...register(input.key, {
|
||||
required
|
||||
})}
|
||||
placeholder={t(input.placeholder || '')}
|
||||
bg={'myGray.50'}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (input.valueType === WorkflowIOValueTypeEnum.number) {
|
||||
return (
|
||||
<NumberInput step={input.step} min={input.min} max={input.max} bg={'myGray.50'}>
|
||||
<NumberInputField
|
||||
{...register(input.key, {
|
||||
required
|
||||
required: input.required,
|
||||
min: input.min,
|
||||
max: input.max,
|
||||
valueAsNumber: true
|
||||
})}
|
||||
placeholder={t(input.placeholder || '')}
|
||||
bg={'myGray.50'}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (input.valueType === WorkflowIOValueTypeEnum.number) {
|
||||
return (
|
||||
<NumberInput step={input.step} min={input.min} max={input.max} bg={'myGray.50'}>
|
||||
<NumberInputField
|
||||
{...register(input.key, {
|
||||
required: input.required,
|
||||
min: input.min,
|
||||
max: input.max,
|
||||
valueAsNumber: true
|
||||
})}
|
||||
/>
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
</NumberInputStepper>
|
||||
</NumberInput>
|
||||
);
|
||||
}
|
||||
if (input.valueType === WorkflowIOValueTypeEnum.boolean) {
|
||||
return (
|
||||
<Box>
|
||||
<Switch size={'lg'} {...register(input.key)} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
if (typeof input.value === 'string') {
|
||||
return (
|
||||
<JsonEditor
|
||||
bg={'myGray.50'}
|
||||
placeholder={t(input.placeholder || '')}
|
||||
resize
|
||||
value={getValues(input.key)}
|
||||
onChange={(e) => {
|
||||
setValue(input.key, e);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})();
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
</NumberInputStepper>
|
||||
</NumberInput>
|
||||
);
|
||||
}
|
||||
if (input.valueType === WorkflowIOValueTypeEnum.boolean) {
|
||||
return (
|
||||
<Box>
|
||||
<Switch size={'lg'} {...register(input.key)} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
if (typeof input.value === 'string') {
|
||||
return (
|
||||
<JsonEditor
|
||||
bg={'myGray.50'}
|
||||
placeholder={t(input.placeholder || '')}
|
||||
resize
|
||||
value={getValues(input.key)}
|
||||
onChange={(e) => {
|
||||
setValue(input.key, e);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})();
|
||||
|
||||
return !!RenderInput ? (
|
||||
<Box key={input.key} _notLast={{ mb: 4 }} px={1}>
|
||||
<Flex alignItems={'center'} mb={1}>
|
||||
<Box position={'relative'}>
|
||||
{required && (
|
||||
<Box position={'absolute'} right={-2} top={'-1px'} color={'red.600'}>
|
||||
*
|
||||
</Box>
|
||||
)}
|
||||
{t(input.debugLabel || input.label)}
|
||||
</Box>
|
||||
{input.description && <QuestionTip ml={2} label={input.description} />}
|
||||
</Flex>
|
||||
{RenderInput}
|
||||
</Box>
|
||||
) : null;
|
||||
})}
|
||||
</Box>
|
||||
<Flex py={2} justifyContent={'flex-end'}>
|
||||
<Button onClick={handleSubmit(onclickRun)}>运行</Button>
|
||||
</Flex>
|
||||
return !!RenderInput ? (
|
||||
<Box key={input.key} _notLast={{ mb: 4 }} px={1}>
|
||||
<Flex alignItems={'center'} mb={1}>
|
||||
<Box position={'relative'}>
|
||||
{required && (
|
||||
<Box position={'absolute'} right={-2} top={'-1px'} color={'red.600'}>
|
||||
*
|
||||
</Box>
|
||||
)}
|
||||
{t(input.debugLabel || input.label)}
|
||||
</Box>
|
||||
{input.description && <QuestionTip ml={2} label={input.description} />}
|
||||
</Flex>
|
||||
{RenderInput}
|
||||
</Box>
|
||||
) : null;
|
||||
})}
|
||||
</Box>
|
||||
<Flex py={2} justifyContent={'flex-end'} px={6}>
|
||||
<Button onClick={handleSubmit(onclickRun)}>运行</Button>
|
||||
</Flex>
|
||||
</MyRightDrawer>
|
||||
);
|
||||
|
@@ -280,7 +280,7 @@ export function RenderHttpProps({
|
||||
);
|
||||
|
||||
return [...moduleVariables, ...globalVariables];
|
||||
}, [inputs, nodeList, t]);
|
||||
}, [appDetail.chatConfig, inputs, nodeList, t]);
|
||||
|
||||
const variableText = useMemo(() => {
|
||||
return variables
|
||||
|
@@ -28,7 +28,7 @@ import MyInput from '@/components/MyInput';
|
||||
import { getElseIFLabel, getHandleId } from '@fastgpt/global/core/workflow/utils';
|
||||
import { SourceHandle } from '../render/Handle';
|
||||
import { Position, useReactFlow } from 'reactflow';
|
||||
import { getReferenceDataValueType } from '@/web/core/workflow/utils';
|
||||
import { getRefData } from '@/web/core/workflow/utils';
|
||||
import DragIcon from '@fastgpt/web/components/common/DndDrag/DragIcon';
|
||||
import { AppContext } from '@/web/core/app/context/appContext';
|
||||
|
||||
@@ -346,8 +346,8 @@ const ConditionSelect = ({
|
||||
const appDetail = useContextSelector(AppContext, (v) => v.appDetail);
|
||||
|
||||
// get condition type
|
||||
const valueType = useMemo(() => {
|
||||
return getReferenceDataValueType({
|
||||
const { valueType, required } = useMemo(() => {
|
||||
return getRefData({
|
||||
variable,
|
||||
nodeList,
|
||||
chatConfig: appDetail.chatConfig,
|
||||
@@ -376,11 +376,22 @@ const ConditionSelect = ({
|
||||
|
||||
return [];
|
||||
}, [valueType]);
|
||||
const filterQuiredConditionList = useMemo(() => {
|
||||
if (required) {
|
||||
return conditionList.filter(
|
||||
(item) =>
|
||||
item.value !== VariableConditionEnum.isEmpty &&
|
||||
item.value !== VariableConditionEnum.isNotEmpty
|
||||
);
|
||||
}
|
||||
return conditionList;
|
||||
}, [conditionList, required]);
|
||||
|
||||
return (
|
||||
<MySelect
|
||||
className="nowheel"
|
||||
w={'100%'}
|
||||
list={conditionList}
|
||||
list={filterQuiredConditionList}
|
||||
value={condition}
|
||||
onchange={onSelect}
|
||||
placeholder="选择条件"
|
||||
|
@@ -1,19 +1,15 @@
|
||||
import React, { Dispatch, useMemo, useTransition } from 'react';
|
||||
import { NodeProps } from 'reactflow';
|
||||
import { Box, Flex, Textarea, useTheme } from '@chakra-ui/react';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { Box, useTheme } from '@chakra-ui/react';
|
||||
import { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/index.d';
|
||||
import { welcomeTextTip } from '@fastgpt/global/core/workflow/template/tip';
|
||||
|
||||
import QGSwitch from '@/components/core/app/QGSwitch';
|
||||
import TTSSelect from '@/components/core/app/TTSSelect';
|
||||
import WhisperConfig from '@/components/core/app/WhisperConfig';
|
||||
import InputGuideConfig from '@/components/core/chat/appConfig/InputGuideConfig';
|
||||
import InputGuideConfig from '@/components/core/app/InputGuideConfig';
|
||||
import { getAppChatConfig } from '@fastgpt/global/core/workflow/utils';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { TTSTypeEnum } from '@/web/core/app/constants';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import NodeCard from './render/NodeCard';
|
||||
import ScheduledTriggerConfig from '@/components/core/app/ScheduledTriggerConfig';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
@@ -22,6 +18,7 @@ import { AppChatConfigType, AppDetailType, VariableItemType } from '@fastgpt/glo
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import VariableEdit from '@/components/core/app/VariableEdit';
|
||||
import { AppContext } from '@/web/core/app/context/appContext';
|
||||
import WelcomeTextConfig from '@/components/core/app/WelcomeTextConfig';
|
||||
|
||||
type ComponentProps = {
|
||||
chatConfig: AppChatConfigType;
|
||||
@@ -94,22 +91,10 @@ function WelcomeText({ chatConfig: { welcomeText }, setAppDetail }: ComponentPro
|
||||
const [, startTst] = useTransition();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex mb={1} alignItems={'center'}>
|
||||
<MyIcon name={'core/modules/welcomeText'} mr={2} w={'14px'} color={'#E74694'} />
|
||||
<Box fontWeight={'medium'}>{t('core.app.Welcome Text')}</Box>
|
||||
<MyTooltip label={t(welcomeTextTip)} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
<Textarea
|
||||
className="nodrag"
|
||||
rows={6}
|
||||
fontSize={'12px'}
|
||||
<Box className="nodrag">
|
||||
<WelcomeTextConfig
|
||||
resize={'both'}
|
||||
defaultValue={welcomeText}
|
||||
bg={'myWhite.500'}
|
||||
placeholder={t(welcomeTextTip)}
|
||||
onChange={(e) => {
|
||||
startTst(() => {
|
||||
setAppDetail((state) => ({
|
||||
@@ -122,7 +107,7 @@ function WelcomeText({ chatConfig: { welcomeText }, setAppDetail }: ComponentPro
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@ import { SmallAddIcon } from '@chakra-ui/icons';
|
||||
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 { getReferenceDataValueType } from '@/web/core/workflow/utils';
|
||||
import { getRefData } from '@/web/core/workflow/utils';
|
||||
import { isReferenceValue } from '@fastgpt/global/core/workflow/utils';
|
||||
import { AppContext } from '@/web/core/app/context/appContext';
|
||||
|
||||
@@ -84,7 +84,7 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps<FlowNodeItemType>) =>
|
||||
return (
|
||||
<>
|
||||
{updateList.map((updateItem, index) => {
|
||||
const valueType = getReferenceDataValueType({
|
||||
const { valueType } = getRefData({
|
||||
variable: updateItem.variable,
|
||||
nodeList,
|
||||
chatConfig: appDetail.chatConfig,
|
||||
|
@@ -32,6 +32,7 @@ const NodeStart = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
id: item.key,
|
||||
type: FlowNodeOutputTypeEnum.static,
|
||||
key: item.key,
|
||||
required: item.required,
|
||||
valueType: item.valueType || WorkflowIOValueTypeEnum.any,
|
||||
label: item.label
|
||||
}));
|
||||
|
@@ -171,6 +171,11 @@ const RenderOutput = ({
|
||||
{renderOutputs.map((output) => {
|
||||
return output.label ? (
|
||||
<Box key={output.key} _notLast={{ mb: 5 }} position={'relative'}>
|
||||
{output.required && (
|
||||
<Box position={'absolute'} left={'-6px'} top={-1} color={'red.600'}>
|
||||
*
|
||||
</Box>
|
||||
)}
|
||||
<OutputLabel nodeId={nodeId} output={output} />
|
||||
</Box>
|
||||
) : null;
|
||||
|
@@ -47,6 +47,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
|
||||
const { teamId, tmbId, dataset } = await authDataset({
|
||||
req,
|
||||
authToken: true,
|
||||
authApiKey: true,
|
||||
per: 'w',
|
||||
datasetId: data.datasetId
|
||||
|
@@ -163,8 +163,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
return authHeaderRequest({
|
||||
req,
|
||||
appId,
|
||||
chatId,
|
||||
detail
|
||||
chatId
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -292,17 +291,19 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
data: '[DONE]'
|
||||
});
|
||||
|
||||
if (responseDetail && detail) {
|
||||
if (detail) {
|
||||
responseWrite({
|
||||
res,
|
||||
event: SseResponseEventEnum.updateVariables,
|
||||
data: JSON.stringify(newVariables)
|
||||
});
|
||||
responseWrite({
|
||||
res,
|
||||
event: SseResponseEventEnum.flowResponses,
|
||||
data: JSON.stringify(feResponseData)
|
||||
});
|
||||
if (responseDetail) {
|
||||
responseWrite({
|
||||
res,
|
||||
event: SseResponseEventEnum.flowResponses,
|
||||
data: JSON.stringify(feResponseData)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
res.end();
|
||||
@@ -443,13 +444,11 @@ const authTeamSpaceChat = async ({
|
||||
const authHeaderRequest = async ({
|
||||
req,
|
||||
appId,
|
||||
chatId,
|
||||
detail
|
||||
chatId
|
||||
}: {
|
||||
req: NextApiRequest;
|
||||
appId?: string;
|
||||
chatId?: string;
|
||||
detail?: boolean;
|
||||
}): Promise<AuthResponseType> => {
|
||||
const {
|
||||
appId: apiKeyAppId,
|
||||
@@ -517,7 +516,7 @@ const authHeaderRequest = async ({
|
||||
tmbId,
|
||||
user,
|
||||
app,
|
||||
responseDetail: detail,
|
||||
responseDetail: true,
|
||||
apikey,
|
||||
authType,
|
||||
canWrite
|
||||
|
@@ -4,7 +4,6 @@ import { AddIcon, QuestionOutlineIcon, SmallAddIcon } from '@chakra-ui/icons';
|
||||
import { useFieldArray, UseFormReturn } from 'react-hook-form';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import type { AppSimpleEditFormType } from '@fastgpt/global/core/app/type.d';
|
||||
import { welcomeTextTip } from '@fastgpt/global/core/workflow/template/tip';
|
||||
import { useRequest } from '@fastgpt/web/hooks/useRequest';
|
||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||
import { useRouter } from 'next/router';
|
||||
@@ -42,14 +41,16 @@ const ToolSelectModal = dynamic(() => import('./ToolSelectModal'), { ssr: false
|
||||
const TTSSelect = dynamic(() => import('@/components/core/app/TTSSelect'), { ssr: false });
|
||||
const QGSwitch = dynamic(() => import('@/components/core/app/QGSwitch'), { ssr: false });
|
||||
const WhisperConfig = dynamic(() => import('@/components/core/app/WhisperConfig'), { ssr: false });
|
||||
const InputGuideConfig = dynamic(
|
||||
() => import('@/components/core/chat/appConfig/InputGuideConfig'),
|
||||
{ ssr: false }
|
||||
);
|
||||
const InputGuideConfig = dynamic(() => import('@/components/core/app/InputGuideConfig'), {
|
||||
ssr: false
|
||||
});
|
||||
const ScheduledTriggerConfig = dynamic(
|
||||
() => import('@/components/core/app/ScheduledTriggerConfig'),
|
||||
{ ssr: false }
|
||||
);
|
||||
const WelcomeTextConfig = dynamic(() => import('@/components/core/app/WelcomeTextConfig'), {
|
||||
ssr: false
|
||||
});
|
||||
|
||||
const BoxStyles: BoxProps = {
|
||||
px: 5,
|
||||
@@ -409,18 +410,7 @@ const EditForm = ({
|
||||
|
||||
{/* welcome */}
|
||||
<Box {...BoxStyles}>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'core/app/simpleMode/chat'} w={'20px'} />
|
||||
<Box mx={2}>{t('core.app.Welcome Text')}</Box>
|
||||
<MyTooltip label={t(welcomeTextTip)} forceShow>
|
||||
<QuestionOutlineIcon />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
<MyTextarea
|
||||
mt={2}
|
||||
bg={'myWhite.400'}
|
||||
rows={5}
|
||||
placeholder={t(welcomeTextTip)}
|
||||
<WelcomeTextConfig
|
||||
defaultValue={getValues('chatConfig.welcomeText')}
|
||||
onBlur={(e) => {
|
||||
setValue('chatConfig.welcomeText', e.target.value || '');
|
||||
|
@@ -83,28 +83,26 @@ const PreviewChunks = ({
|
||||
isLoading={isLoading}
|
||||
maxW={['90vw', '40vw']}
|
||||
>
|
||||
<Flex flexDirection={'column'} height={'100%'} overflowY={'auto'}>
|
||||
{data.map((item, index) => (
|
||||
<Box
|
||||
key={index}
|
||||
whiteSpace={'pre-wrap'}
|
||||
fontSize={'sm'}
|
||||
p={4}
|
||||
bg={index % 2 === 0 ? 'white' : 'myWhite.600'}
|
||||
mb={3}
|
||||
borderRadius={'md'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'borderColor.low'}
|
||||
boxShadow={'2'}
|
||||
_notLast={{
|
||||
mb: 2
|
||||
}}
|
||||
>
|
||||
<Box color={'myGray.900'}>{item.q}</Box>
|
||||
<Box color={'myGray.500'}>{item.a}</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
{data.map((item, index) => (
|
||||
<Box
|
||||
key={index}
|
||||
whiteSpace={'pre-wrap'}
|
||||
fontSize={'sm'}
|
||||
p={4}
|
||||
bg={index % 2 === 0 ? 'white' : 'myWhite.600'}
|
||||
mb={3}
|
||||
borderRadius={'md'}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'borderColor.low'}
|
||||
boxShadow={'2'}
|
||||
_notLast={{
|
||||
mb: 2
|
||||
}}
|
||||
>
|
||||
<Box color={'myGray.900'}>{item.q}</Box>
|
||||
<Box color={'myGray.500'}>{item.a}</Box>
|
||||
</Box>
|
||||
))}
|
||||
</MyRightDrawer>
|
||||
);
|
||||
};
|
||||
|
@@ -33,8 +33,8 @@ import ParentPaths from '@/components/common/ParentPaths';
|
||||
import DatasetTypeTag from '@/components/core/dataset/DatasetTypeTag';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { xmlDownloadFetch } from '@/web/common/api/xmlFetch';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import { downloadFetch } from '@/web/common/system/utils';
|
||||
|
||||
const CreateModal = dynamic(() => import('./component/CreateModal'), { ssr: false });
|
||||
const MoveModal = dynamic(() => import('./component/MoveModal'), { ssr: false });
|
||||
@@ -93,7 +93,7 @@ const Dataset = () => {
|
||||
setLoading(true);
|
||||
await checkTeamExportDatasetLimit(dataset._id);
|
||||
|
||||
await xmlDownloadFetch({
|
||||
await downloadFetch({
|
||||
url: `/api/core/dataset/exportAll?datasetId=${dataset._id}`,
|
||||
filename: `${dataset.name}.csv`
|
||||
});
|
||||
|
@@ -50,19 +50,15 @@ const Render = ({ pluginId }: Props) => {
|
||||
edges: pluginDetail?.edges || []
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isV2Workflow) {
|
||||
initData(JSON.parse(workflowStringData));
|
||||
}
|
||||
}, [initData, isV2Workflow, workflowStringData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isV2Workflow && pluginDetail) {
|
||||
openConfirm(() => {
|
||||
initData(JSON.parse(JSON.stringify(v1Workflow2V2((pluginDetail.modules || []) as any))));
|
||||
})();
|
||||
} else {
|
||||
initData(JSON.parse(workflowStringData));
|
||||
}
|
||||
}, [initData, isV2Workflow, openConfirm, pluginDetail]);
|
||||
}, [pluginDetail]);
|
||||
|
||||
useBeforeunload({
|
||||
tip: t('core.common.tip.leave page')
|
||||
|
@@ -2,7 +2,6 @@ import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/cons
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d';
|
||||
import type { StartChatFnProps } from '@/components/ChatBox/type.d';
|
||||
import { getToken } from '@/web/support/user/auth';
|
||||
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||
import dayjs from 'dayjs';
|
||||
import {
|
||||
@@ -117,8 +116,7 @@ export const streamFetch = ({
|
||||
const requestData = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
token: getToken()
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
signal: abortCtrl.signal,
|
||||
body: JSON.stringify({
|
||||
|
@@ -4,7 +4,7 @@ import axios, {
|
||||
AxiosResponse,
|
||||
AxiosProgressEvent
|
||||
} from 'axios';
|
||||
import { clearToken, getToken } from '@/web/support/user/auth';
|
||||
import { clearToken } from '@/web/support/user/auth';
|
||||
import { TOKEN_ERROR_CODE } from '@fastgpt/global/common/error/errorCode';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
import { useSystemStore } from '../system/useSystemStore';
|
||||
@@ -15,6 +15,7 @@ interface ConfigType {
|
||||
onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
||||
cancelToken?: AbortController;
|
||||
maxQuantity?: number;
|
||||
withCredentials?: boolean;
|
||||
}
|
||||
interface ResponseDataType {
|
||||
code: number;
|
||||
@@ -61,7 +62,6 @@ function requestFinish({ url }: { url: string }) {
|
||||
*/
|
||||
function startInterceptors(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
|
||||
if (config.headers) {
|
||||
config.headers.token = getToken();
|
||||
}
|
||||
|
||||
return config;
|
||||
@@ -138,7 +138,7 @@ instance.interceptors.response.use(responseSuccess, (err) => Promise.reject(err)
|
||||
function request(
|
||||
url: string,
|
||||
data: any,
|
||||
{ cancelToken, maxQuantity, ...config }: ConfigType,
|
||||
{ cancelToken, maxQuantity, withCredentials, ...config }: ConfigType,
|
||||
method: Method
|
||||
): any {
|
||||
/* 去空 */
|
||||
@@ -158,6 +158,7 @@ function request(
|
||||
data: ['POST', 'PUT'].includes(method) ? data : null,
|
||||
params: !['POST', 'PUT'].includes(method) ? data : null,
|
||||
signal: cancelToken?.signal,
|
||||
withCredentials,
|
||||
...config // 用户自定义配置,可以覆盖前面的配置
|
||||
})
|
||||
.then((res) => checkRes(res.data))
|
||||
|
@@ -1,31 +0,0 @@
|
||||
import { getToken } from '@/web/support/user/auth';
|
||||
import { hasHttps } from '@fastgpt/web/common/system/utils';
|
||||
|
||||
export const xmlDownloadFetch = async ({ url, filename }: { url: string; filename: string }) => {
|
||||
if (hasHttps()) {
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
} else {
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
token: `${getToken()}`
|
||||
}
|
||||
});
|
||||
if (!response.ok) throw new Error('Network response was not ok.');
|
||||
|
||||
const blob = await response.blob();
|
||||
const downloadUrl = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none'; // 隐藏<a>元素
|
||||
a.href = downloadUrl;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click(); // 模拟用户点击
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(downloadUrl); // 清理生成的URL
|
||||
}
|
||||
};
|
8
projects/app/src/web/common/system/utils.ts
Normal file
8
projects/app/src/web/common/system/utils.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export const downloadFetch = async ({ url, filename }: { url: string; filename: string }) => {
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
};
|
@@ -5,7 +5,6 @@ import type { AppTTSConfigType } from '@fastgpt/global/core/app/type.d';
|
||||
import { TTSTypeEnum } from '@/web/core/app/constants';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import type { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat.d';
|
||||
import { getToken } from '@/web/support/user/auth';
|
||||
import { useMount } from 'ahooks';
|
||||
|
||||
const contentType = 'audio/mpeg';
|
||||
@@ -41,8 +40,7 @@ export const useAudioPlay = (props?: OutLinkChatAuthProps & { ttsConfig?: AppTTS
|
||||
const response = await fetch('/api/core/chat/item/getSpeech', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
token: getToken()
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
signal: audioController.current.signal,
|
||||
body: JSON.stringify({
|
||||
|
@@ -701,6 +701,7 @@ export const getSystemVariables = (t: TFunction): EditorVariablePickerType[] =>
|
||||
{
|
||||
key: 'appId',
|
||||
label: t('core.module.http.AppId'),
|
||||
required: true,
|
||||
valueType: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
@@ -716,11 +717,13 @@ export const getSystemVariables = (t: TFunction): EditorVariablePickerType[] =>
|
||||
{
|
||||
key: 'histories',
|
||||
label: t('core.module.http.Histories'),
|
||||
required: true,
|
||||
valueType: WorkflowIOValueTypeEnum.chatHistory
|
||||
},
|
||||
{
|
||||
key: 'cTime',
|
||||
label: t('core.module.http.Current time'),
|
||||
required: true,
|
||||
valueType: WorkflowIOValueTypeEnum.string
|
||||
}
|
||||
];
|
||||
|
@@ -26,10 +26,11 @@ export const getCountChatInputGuideTotal = (data: countChatInputGuideTotalQuery)
|
||||
export const getChatInputGuideList = (data: ChatInputGuideProps) =>
|
||||
GET<ChatInputGuideResponse>(`/core/chat/inputGuide/list`, data);
|
||||
|
||||
export const queryChatInputGuideList = (
|
||||
data: QueryChatInputGuideProps,
|
||||
url = `/core/chat/inputGuide/query`
|
||||
) => GET<QueryChatInputGuideResponse>(url, data);
|
||||
export const queryChatInputGuideList = (data: QueryChatInputGuideProps, url?: string) => {
|
||||
return GET<QueryChatInputGuideResponse>(url ?? `/core/chat/inputGuide/query`, data, {
|
||||
withCredentials: !url
|
||||
});
|
||||
};
|
||||
|
||||
export const postChatInputGuides = (data: createInputGuideBody) =>
|
||||
POST<createInputGuideResponse>(`/core/chat/inputGuide/create`, data);
|
||||
|
@@ -428,7 +428,7 @@ export const v1Workflow2V2 = (
|
||||
pluginId,
|
||||
pluginType: node.pluginType,
|
||||
parentId: node.parentId,
|
||||
version: 'v2.0',
|
||||
version: '481',
|
||||
|
||||
inputs,
|
||||
outputs
|
||||
|
@@ -157,7 +157,7 @@ export const computedNodeInputReference = ({
|
||||
|
||||
return sourceNodes;
|
||||
};
|
||||
export const getReferenceDataValueType = ({
|
||||
export const getRefData = ({
|
||||
variable,
|
||||
nodeList,
|
||||
chatConfig,
|
||||
@@ -168,16 +168,34 @@ export const getReferenceDataValueType = ({
|
||||
chatConfig: AppChatConfigType;
|
||||
t: TFunction;
|
||||
}) => {
|
||||
if (!variable) return WorkflowIOValueTypeEnum.any;
|
||||
if (!variable)
|
||||
return {
|
||||
valueType: WorkflowIOValueTypeEnum.any,
|
||||
required: false
|
||||
};
|
||||
|
||||
const node = nodeList.find((node) => node.nodeId === variable[0]);
|
||||
const systemVariables = getWorkflowGlobalVariables({ nodes: nodeList, chatConfig, t });
|
||||
|
||||
if (!node) return systemVariables.find((item) => item.key === variable?.[1])?.valueType;
|
||||
if (!node) {
|
||||
const globalVariable = systemVariables.find((item) => item.key === variable?.[1]);
|
||||
return {
|
||||
valueType: globalVariable?.valueType || WorkflowIOValueTypeEnum.any,
|
||||
required: !!globalVariable?.required
|
||||
};
|
||||
}
|
||||
|
||||
const output = node.outputs.find((item) => item.id === variable[1]);
|
||||
if (!output) return WorkflowIOValueTypeEnum.any;
|
||||
return output.valueType;
|
||||
if (!output)
|
||||
return {
|
||||
valueType: WorkflowIOValueTypeEnum.any,
|
||||
required: false
|
||||
};
|
||||
|
||||
return {
|
||||
valueType: output.valueType,
|
||||
required: !!output.required
|
||||
};
|
||||
};
|
||||
|
||||
/* Connection rules */
|
||||
|
Reference in New Issue
Block a user