4.8.1 test-fix (#1561)

This commit is contained in:
Archer
2024-05-22 18:49:39 +08:00
committed by GitHub
parent 87e4afe89b
commit b1aafde7c9
65 changed files with 1245 additions and 293 deletions

View File

@@ -30,7 +30,7 @@ export default function InputGuideBox({
return await queryChatInputGuideList(
{
appId,
searchKey: text
searchKey: text.slice(0, 50)
},
chatInputGuide.customUrl ? chatInputGuide.customUrl : undefined
);

View File

@@ -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);
}}
/>

View File

@@ -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';

View File

@@ -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')}>

View File

@@ -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>

View File

@@ -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';

View File

@@ -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

View 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;

View File

@@ -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 />}

View 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;

View File

@@ -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"
/>

View File

@@ -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>
);

View File

@@ -280,7 +280,7 @@ export function RenderHttpProps({
);
return [...moduleVariables, ...globalVariables];
}, [inputs, nodeList, t]);
}, [appDetail.chatConfig, inputs, nodeList, t]);
const variableText = useMemo(() => {
return variables

View File

@@ -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="选择条件"

View File

@@ -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>
);
}

View File

@@ -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,

View File

@@ -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
}));

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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 || '');

View File

@@ -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>
);
};

View File

@@ -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`
});

View File

@@ -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')

View File

@@ -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({

View File

@@ -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))

View File

@@ -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
}
};

View 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);
};

View File

@@ -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({

View File

@@ -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
}
];

View File

@@ -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);

View File

@@ -428,7 +428,7 @@ export const v1Workflow2V2 = (
pluginId,
pluginType: node.pluginType,
parentId: node.parentId,
version: 'v2.0',
version: '481',
inputs,
outputs

View File

@@ -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 */