mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-30 18:48:55 +00:00
4.6.8-alpha (#804)
* perf: redirect request and err log replace perf: dataset openapi feat: session fix: retry input error feat: 468 doc sub page feat: standard sub perf: rerank tip perf: rerank tip perf: api sdk perf: openapi sub plan perf: sub ui fix: ts * perf: init log * fix: variable select * sub page * icon * perf: llm model config * perf: menu ux * perf: system store * perf: publish app name * fix: init data * perf: flow edit ux * fix: value type format and ux * fix prompt editor default value (#13) * fix prompt editor default value * fix prompt editor update when not focus * add key with variable --------- Co-authored-by: Archer <545436317@qq.com> * fix: value type * doc * i18n * import path * home page * perf: mongo session running * fix: ts * perf: use toast * perf: flow edit * perf: sse response * slider ui * fetch error * fix prompt editor rerender when not focus by key defaultvalue (#14) * perf: prompt editor * feat: dataset search concat * perf: doc * fix:ts * perf: doc * fix json editor onblur value (#15) * faq * vector model default config * ipv6 --------- Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
@@ -13,7 +13,7 @@ import { throttle } from 'lodash';
|
||||
import type { ExportChatType } from '@/types/chat.d';
|
||||
import type { ChatItemType, ChatSiteItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useAudioPlay } from '@/web/common/utils/voice';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
Textarea,
|
||||
Checkbox
|
||||
} from '@chakra-ui/react';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
|
||||
import { adaptChat2GptMessages } from '@fastgpt/global/core/chat/adapt';
|
||||
import { useMarkdown } from '@/web/common/hooks/useMarkdown';
|
||||
@@ -159,7 +158,7 @@ const ChatBox = (
|
||||
const router = useRouter();
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const { isPc, setLoading } = useSystemStore();
|
||||
const { isPc, setLoading, feConfigs } = useSystemStore();
|
||||
const TextareaDom = useRef<HTMLTextAreaElement>(null);
|
||||
const chatController = useRef(new AbortController());
|
||||
const questionGuideController = useRef(new AbortController());
|
||||
@@ -519,7 +518,13 @@ const ChatBox = (
|
||||
chatHistory.length === 0 &&
|
||||
!variableModules?.length &&
|
||||
!welcomeText,
|
||||
[chatHistory.length, showEmptyIntro, variableModules, welcomeText]
|
||||
[
|
||||
chatHistory.length,
|
||||
feConfigs?.show_emptyChat,
|
||||
showEmptyIntro,
|
||||
variableModules?.length,
|
||||
welcomeText
|
||||
]
|
||||
);
|
||||
const statusBoxData = useMemo(() => {
|
||||
const colorMap = {
|
||||
@@ -954,7 +959,6 @@ const ChatBox = (
|
||||
setAdminMarkData={(e) => setAdminMarkData({ ...e, chatItemId: adminMarkData.chatItemId })}
|
||||
onClose={() => setAdminMarkData(undefined)}
|
||||
onSuccess={(adminFeedback) => {
|
||||
console.log(adminMarkData);
|
||||
if (!appId || !chatId || !adminMarkData.chatItemId) return;
|
||||
updateChatAdminFeedback({
|
||||
appId,
|
||||
@@ -1108,6 +1112,7 @@ const VariableInput = React.memo(function VariableInput({
|
||||
}>;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const { register, setValue, handleSubmit: handleSubmitChat, watch } = chatForm;
|
||||
const variables = watch('variables');
|
||||
|
||||
@@ -1168,6 +1173,7 @@ const VariableInput = React.memo(function VariableInput({
|
||||
value={variables[item.key]}
|
||||
onchange={(e) => {
|
||||
setValue(`variables.${item.key}`, e);
|
||||
setRefresh((state) => !state);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@@ -3,10 +3,12 @@ import { Button, ModalFooter, ModalBody } from '@chakra-ui/react';
|
||||
import MyModal from '../MyModal';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import Markdown from '../Markdown';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
const CommunityModal = ({ onClose }: { onClose: () => void }) => {
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
isOpen={true}
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import { useRouter } from 'next/router';
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const unAuthPage: { [key: string]: boolean } = {
|
||||
'/': true,
|
||||
@@ -10,16 +11,14 @@ const unAuthPage: { [key: string]: boolean } = {
|
||||
'/login/fastlogin': true,
|
||||
'/appStore': true,
|
||||
'/chat/share': true,
|
||||
'/tools/price': true
|
||||
'/tools/price': true,
|
||||
'/price': true
|
||||
};
|
||||
|
||||
const Auth = ({ children }: { children: JSX.Element }) => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const toast = useToast({
|
||||
title: '请先登录',
|
||||
position: 'top',
|
||||
status: 'warning'
|
||||
});
|
||||
const { toast } = useToast();
|
||||
const { userInfo, initUserInfo } = useUserStore();
|
||||
|
||||
useQuery(
|
||||
@@ -37,12 +36,15 @@ const Auth = ({ children }: { children: JSX.Element }) => {
|
||||
router.replace(
|
||||
`/login?lastRoute=${encodeURIComponent(location.pathname + location.search)}`
|
||||
);
|
||||
toast();
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: t('support.user.Need to login')
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return userInfo || unAuthPage[router.pathname] === true ? children : null;
|
||||
return !!userInfo || unAuthPage[router.pathname] === true ? children : null;
|
||||
};
|
||||
|
||||
export default Auth;
|
||||
|
@@ -7,7 +7,6 @@ import { throttle } from 'lodash';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { getUnreadCount } from '@/web/support/user/inform/api';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
import Auth from './auth';
|
||||
@@ -26,7 +25,8 @@ const pcUnShowLayoutRoute: Record<string, boolean> = {
|
||||
'/chat/share': true,
|
||||
'/app/edit': true,
|
||||
'/chat': true,
|
||||
'/tools/price': true
|
||||
'/tools/price': true,
|
||||
'/price': true
|
||||
};
|
||||
const phoneUnShowLayoutRoute: Record<string, boolean> = {
|
||||
'/': true,
|
||||
@@ -34,14 +34,15 @@ const phoneUnShowLayoutRoute: Record<string, boolean> = {
|
||||
'/login/provider': true,
|
||||
'/login/fastlogin': true,
|
||||
'/chat/share': true,
|
||||
'/tools/price': true
|
||||
'/tools/price': true,
|
||||
'/price': true
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: JSX.Element }) => {
|
||||
const router = useRouter();
|
||||
const { colorMode, setColorMode } = useColorMode();
|
||||
const { Loading } = useLoading();
|
||||
const { loading, setScreenWidth, isPc } = useSystemStore();
|
||||
const { loading, setScreenWidth, isPc, feConfigs } = useSystemStore();
|
||||
const { userInfo } = useUserStore();
|
||||
|
||||
const isChatPage = useMemo(
|
||||
@@ -74,12 +75,14 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
||||
refetchInterval: 10000
|
||||
});
|
||||
|
||||
const isHideNavbar = !!pcUnShowLayoutRoute[router.pathname];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box h={'100%'} bg={'myGray.100'}>
|
||||
{isPc === true && (
|
||||
<>
|
||||
{pcUnShowLayoutRoute[router.pathname] ? (
|
||||
{isHideNavbar ? (
|
||||
<Auth>{children}</Auth>
|
||||
) : (
|
||||
<>
|
||||
|
@@ -4,7 +4,6 @@ import { useRouter } from 'next/router';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { useChatStore } from '@/web/core/chat/storeChat';
|
||||
import { HUMAN_ICON } from '@fastgpt/global/common/system/constants';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import NextLink from 'next/link';
|
||||
import Badge from '../Badge';
|
||||
import Avatar from '../Avatar';
|
||||
@@ -23,7 +22,7 @@ const Navbar = ({ unread }: { unread: number }) => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const { userInfo } = useUserStore();
|
||||
const { gitStar } = useSystemStore();
|
||||
const { gitStar, feConfigs } = useSystemStore();
|
||||
const { lastChatAppId, lastChatId } = useChatStore();
|
||||
const navbarList = useMemo(
|
||||
() => [
|
||||
@@ -159,7 +158,7 @@ const Navbar = ({ unread }: { unread: number }) => {
|
||||
color={'myGray.500'}
|
||||
>
|
||||
<Badge count={unread}>
|
||||
<MyIcon name={'inform'} width={'22px'} height={'22px'} />
|
||||
<MyIcon name={'support/user/informLight'} width={'22px'} height={'22px'} />
|
||||
</Badge>
|
||||
</Link>
|
||||
</Box>
|
||||
|
@@ -1,18 +1,27 @@
|
||||
import React from 'react';
|
||||
import { Menu, MenuList, MenuItem } from '@chakra-ui/react';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { Menu, MenuList, MenuItem, Box, useOutsideClick, MenuButton } from '@chakra-ui/react';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
||||
interface Props {
|
||||
width: number;
|
||||
width?: number | string;
|
||||
offset?: [number, number];
|
||||
Button: React.ReactNode;
|
||||
trigger?: 'hover' | 'click';
|
||||
menuList: {
|
||||
isActive?: boolean;
|
||||
child: React.ReactNode;
|
||||
label: string | React.ReactNode;
|
||||
icon?: string;
|
||||
onClick: () => any;
|
||||
}[];
|
||||
}
|
||||
|
||||
const MyMenu = ({ width, offset = [0, 10], Button, menuList }: Props) => {
|
||||
const MyMenu = ({
|
||||
width = 'auto',
|
||||
trigger = 'hover',
|
||||
offset = [0, 5],
|
||||
Button,
|
||||
menuList
|
||||
}: Props) => {
|
||||
const menuItemStyles = {
|
||||
borderRadius: 'sm',
|
||||
py: 3,
|
||||
@@ -23,31 +32,80 @@ const MyMenu = ({ width, offset = [0, 10], Button, menuList }: Props) => {
|
||||
color: 'primary.600'
|
||||
}
|
||||
};
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const closeTimer = useRef<any>();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
useOutsideClick({
|
||||
ref: ref,
|
||||
handler: () => {
|
||||
setIsOpen(false);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Menu offset={offset} autoSelect={false} isLazy>
|
||||
{Button}
|
||||
<MenuList
|
||||
minW={`${width}px !important`}
|
||||
p={'6px'}
|
||||
border={'1px solid #fff'}
|
||||
boxShadow={'0px 2px 4px rgba(161, 167, 179, 0.25), 0px 0px 1px rgba(121, 141, 159, 0.25);'}
|
||||
<Menu offset={offset} isOpen={isOpen} autoSelect={false} direction={'ltr'} isLazy>
|
||||
<Box
|
||||
ref={ref}
|
||||
onMouseEnter={() => {
|
||||
if (trigger === 'hover') {
|
||||
setIsOpen(true);
|
||||
}
|
||||
clearTimeout(closeTimer.current);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
if (trigger === 'hover') {
|
||||
closeTimer.current = setTimeout(() => {
|
||||
setIsOpen(false);
|
||||
}, 100);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{menuList.map((item, i) => (
|
||||
<MenuItem
|
||||
key={i}
|
||||
{...menuItemStyles}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
item.onClick && item.onClick();
|
||||
}}
|
||||
color={item.isActive ? 'primary.700' : 'myGray.600'}
|
||||
whiteSpace={'pre-wrap'}
|
||||
>
|
||||
{item.child}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
<Box
|
||||
position={'relative'}
|
||||
onClickCapture={() => {
|
||||
if (trigger === 'click') {
|
||||
setIsOpen(!isOpen);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<MenuButton
|
||||
w={'100%'}
|
||||
h={'100%'}
|
||||
position={'absolute'}
|
||||
top={0}
|
||||
right={0}
|
||||
bottom={0}
|
||||
left={0}
|
||||
/>
|
||||
<Box position={'relative'}>{Button}</Box>
|
||||
</Box>
|
||||
<MenuList
|
||||
minW={isOpen ? `${width}px !important` : 0}
|
||||
p={'6px'}
|
||||
border={'1px solid #fff'}
|
||||
boxShadow={
|
||||
'0px 2px 4px rgba(161, 167, 179, 0.25), 0px 0px 1px rgba(121, 141, 159, 0.25);'
|
||||
}
|
||||
>
|
||||
{menuList.map((item, i) => (
|
||||
<MenuItem
|
||||
key={i}
|
||||
{...menuItemStyles}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setIsOpen(false);
|
||||
item.onClick && item.onClick();
|
||||
}}
|
||||
color={item.isActive ? 'primary.700' : 'myGray.600'}
|
||||
whiteSpace={'pre-wrap'}
|
||||
>
|
||||
{!!item.icon && <MyIcon name={item.icon as any} w={'16px'} mr={2} />}
|
||||
{item.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
</Box>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
@@ -4,11 +4,13 @@ import MySelect, { type SelectProps } from './index';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useDisclosure } from '@chakra-ui/react';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
const PriceBox = dynamic(() => import('@/components/support/wallet/Price'));
|
||||
|
||||
const SelectAiModel = ({ list, ...props }: SelectProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const expandList = useMemo(() => {
|
||||
return feConfigs.show_pay
|
||||
? list.concat({
|
||||
@@ -16,7 +18,7 @@ const SelectAiModel = ({ list, ...props }: SelectProps) => {
|
||||
value: 'price'
|
||||
})
|
||||
: list;
|
||||
}, [list, t]);
|
||||
}, [feConfigs.show_pay, list, t]);
|
||||
|
||||
const {
|
||||
isOpen: isOpenPriceBox,
|
||||
|
@@ -42,63 +42,76 @@ const MySlider = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<Slider
|
||||
max={max}
|
||||
min={min}
|
||||
step={step}
|
||||
size={'lg'}
|
||||
value={value}
|
||||
width={width}
|
||||
onChange={onChange}
|
||||
>
|
||||
{markList?.map((item, i) => (
|
||||
<SliderMark
|
||||
key={item.value}
|
||||
value={item.value}
|
||||
fontSize={'sm'}
|
||||
mt={3}
|
||||
whiteSpace={'nowrap'}
|
||||
transform={'translateX(-50%)'}
|
||||
color={'myGray.600'}
|
||||
>
|
||||
<Box px={3} cursor={'pointer'}>
|
||||
{item.label}
|
||||
</Box>
|
||||
</SliderMark>
|
||||
))}
|
||||
<SliderMark
|
||||
<Box pb={4} zIndex={10}>
|
||||
<Slider
|
||||
max={max}
|
||||
min={min}
|
||||
step={step}
|
||||
size={'lg'}
|
||||
value={value}
|
||||
textAlign="center"
|
||||
bg="primary.500"
|
||||
color="white"
|
||||
px={1}
|
||||
minW={'18px'}
|
||||
w={'auto'}
|
||||
h={'18px'}
|
||||
lineHeight={'18px'}
|
||||
borderRadius={'18px'}
|
||||
transform={'translate(-50%, -155%)'}
|
||||
fontSize={'11px'}
|
||||
>
|
||||
<Box transform={'scale(0.9)'}>{value}</Box>
|
||||
</SliderMark>
|
||||
<SliderTrack
|
||||
bg={'#EAEDF3'}
|
||||
overflow={'visible'}
|
||||
h={'4px'}
|
||||
_before={{
|
||||
...startEndPointStyle,
|
||||
left: '-3px'
|
||||
width={width}
|
||||
onChange={onChange}
|
||||
_hover={{
|
||||
'& .marker': {
|
||||
display: 'block'
|
||||
}
|
||||
}}
|
||||
_after={{
|
||||
...startEndPointStyle,
|
||||
right: '-3px'
|
||||
_active={{
|
||||
'& .marker': {
|
||||
display: 'block'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SliderFilledTrack bg={'primary.500'} />
|
||||
</SliderTrack>
|
||||
<SliderThumb border={'3px solid'} borderColor={'primary.500'}></SliderThumb>
|
||||
</Slider>
|
||||
{markList?.map((item, i) => (
|
||||
<SliderMark
|
||||
key={item.value}
|
||||
value={item.value}
|
||||
fontSize={'sm'}
|
||||
mt={2}
|
||||
whiteSpace={'nowrap'}
|
||||
transform={'translateX(-50%)'}
|
||||
color={'myGray.600'}
|
||||
>
|
||||
<Box px={3} cursor={'pointer'}>
|
||||
{item.label}
|
||||
</Box>
|
||||
</SliderMark>
|
||||
))}
|
||||
<SliderMark
|
||||
className="marker"
|
||||
value={value}
|
||||
textAlign="center"
|
||||
bg="primary.500"
|
||||
color="white"
|
||||
px={1}
|
||||
minW={'20px'}
|
||||
w={'auto'}
|
||||
py={'1px'}
|
||||
borderRadius={'md'}
|
||||
transform={'translate(-50%, -155%)'}
|
||||
fontSize={'11px'}
|
||||
display={'none'}
|
||||
>
|
||||
<Box transform={'scale(0.9)'}>{value}</Box>
|
||||
</SliderMark>
|
||||
<SliderTrack
|
||||
bg={'#EAEDF3'}
|
||||
overflow={'visible'}
|
||||
h={'4px'}
|
||||
_before={{
|
||||
...startEndPointStyle,
|
||||
left: '-3px'
|
||||
}}
|
||||
_after={{
|
||||
...startEndPointStyle,
|
||||
right: '-3px'
|
||||
}}
|
||||
>
|
||||
<SliderFilledTrack bg={'primary.500'} />
|
||||
</SliderTrack>
|
||||
<SliderThumb border={'3px solid'} borderColor={'primary.500'}></SliderThumb>
|
||||
</Slider>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -9,7 +9,7 @@ import {
|
||||
TagLabel,
|
||||
useTheme
|
||||
} from '@chakra-ui/react';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
type Props = BoxProps & { defaultValues: string[]; onUpdate: (e: string[]) => void };
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { Box, BoxProps, Image } from '@chakra-ui/react';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
@@ -7,17 +7,15 @@ import {
|
||||
BoxProps,
|
||||
Button,
|
||||
Flex,
|
||||
Image,
|
||||
Link,
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
Switch,
|
||||
Textarea
|
||||
Switch
|
||||
} from '@chakra-ui/react';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { Prompt_QuotePromptList, Prompt_QuoteTemplateList } from '@/global/core/prompt/AIChat';
|
||||
import { chatModelList, feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import MySlider from '@/components/Slider';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import dynamic from 'next/dynamic';
|
||||
@@ -27,7 +25,7 @@ import type { AppSimpleEditConfigTemplateType } from '@fastgpt/global/core/app/t
|
||||
import { SimpleModeTemplate_FastGPT_Universal } from '@/global/core/app/constants';
|
||||
import { getDocPath } from '@/web/common/system/doc';
|
||||
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
|
||||
import { PickerMenuItemType } from '@fastgpt/web/components/common/Textarea/PromptEditor/type';
|
||||
import { EditorVariablePickerType } from '@fastgpt/web/components/common/Textarea/PromptEditor/type';
|
||||
|
||||
const PromptTemplate = dynamic(() => import('@/components/PromptTemplate'));
|
||||
|
||||
@@ -44,14 +42,17 @@ const AIChatSettingsModal = ({
|
||||
onSuccess: (e: AIChatModuleProps) => void;
|
||||
defaultData: AIChatModuleProps;
|
||||
simpleModeTemplate?: AppSimpleEditConfigTemplateType;
|
||||
pickerMenu?: PickerMenuItemType[];
|
||||
pickerMenu?: EditorVariablePickerType[];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const { feConfigs, llmModelList } = useSystemStore();
|
||||
|
||||
const { register, handleSubmit, getValues, setValue } = useForm({
|
||||
const { handleSubmit, getValues, setValue, watch } = useForm({
|
||||
defaultValues: defaultData
|
||||
});
|
||||
const aiChatQuoteTemplate = watch(ModuleInputKeyEnum.aiChatQuoteTemplate);
|
||||
const aiChatQuotePrompt = watch(ModuleInputKeyEnum.aiChatQuotePrompt);
|
||||
|
||||
const [selectTemplateData, setSelectTemplateData] = useState<{
|
||||
title: string;
|
||||
@@ -60,10 +61,10 @@ const AIChatSettingsModal = ({
|
||||
|
||||
const tokenLimit = useMemo(() => {
|
||||
return (
|
||||
chatModelList.find((item) => item.model === getValues(ModuleInputKeyEnum.aiModel))
|
||||
llmModelList.find((item) => item.model === getValues(ModuleInputKeyEnum.aiModel))
|
||||
?.maxResponse || 4000
|
||||
);
|
||||
}, [getValues]);
|
||||
}, [getValues, llmModelList]);
|
||||
|
||||
const quoteTemplateVariables = (() => [
|
||||
{
|
||||
@@ -160,7 +161,7 @@ const AIChatSettingsModal = ({
|
||||
</Flex>
|
||||
)}
|
||||
{simpleModeTemplate?.systemForm?.aiSettings?.temperature && (
|
||||
<Flex alignItems={'center'} mb={10} mt={isAdEdit ? 8 : 5}>
|
||||
<Flex mb={10} mt={isAdEdit ? 8 : 6}>
|
||||
<Box {...LabelStyles} mr={2} w={'80px'}>
|
||||
{t('core.app.Temperature')}
|
||||
</Box>
|
||||
@@ -183,7 +184,7 @@ const AIChatSettingsModal = ({
|
||||
</Flex>
|
||||
)}
|
||||
{simpleModeTemplate?.systemForm?.aiSettings?.maxToken && (
|
||||
<Flex alignItems={'center'} mt={12} mb={10}>
|
||||
<Flex mt={5} mb={5}>
|
||||
<Box {...LabelStyles} mr={2} w={'80px'}>
|
||||
{t('core.app.Max tokens')}
|
||||
</Box>
|
||||
@@ -239,10 +240,10 @@ const AIChatSettingsModal = ({
|
||||
placeholder={t('template.Quote Content Tip', {
|
||||
default: Prompt_QuoteTemplateList[0].value
|
||||
})}
|
||||
defaultValue={getValues(ModuleInputKeyEnum.aiChatQuoteTemplate)}
|
||||
value={aiChatQuoteTemplate}
|
||||
onChange={(e) => {
|
||||
setValue(ModuleInputKeyEnum.aiChatQuoteTemplate, e);
|
||||
setRefresh(!refresh);
|
||||
// setRefresh(!refresh);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@@ -265,7 +266,7 @@ const AIChatSettingsModal = ({
|
||||
placeholder={t('template.Quote Prompt Tip', {
|
||||
default: Prompt_QuotePromptList[0].value
|
||||
})}
|
||||
defaultValue={getValues(ModuleInputKeyEnum.aiChatQuotePrompt)}
|
||||
value={aiChatQuotePrompt}
|
||||
onChange={(e) => {
|
||||
setValue(ModuleInputKeyEnum.aiChatQuotePrompt, e);
|
||||
}}
|
||||
|
@@ -17,7 +17,7 @@ import MyTooltip from '@/components/MyTooltip';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { reRankModelList } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
@@ -45,6 +45,7 @@ const DatasetParamsModal = ({
|
||||
}: DatasetParamsProps & { onClose: () => void; onSuccess: (e: DatasetParamsProps) => void }) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const { reRankModelList } = useSystemStore();
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const { register, setValue, getValues, handleSubmit } = useForm<DatasetParamsProps>({
|
||||
defaultValues: {
|
||||
@@ -72,7 +73,7 @@ const DatasetParamsModal = ({
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}, [getValues, similarity, refresh]);
|
||||
}, [getValues, similarity]);
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
@@ -135,7 +136,7 @@ const DatasetParamsModal = ({
|
||||
)}
|
||||
|
||||
{limit !== undefined && (
|
||||
<Box display={['block', 'flex']} py={8} mt={3}>
|
||||
<Box display={['block', 'flex']} mt={5}>
|
||||
<Box flex={'0 0 120px'} mb={[8, 0]}>
|
||||
{t('core.dataset.search.Max Tokens')}
|
||||
<MyTooltip label={t('core.dataset.search.Max Tokens Tips')} forceShow>
|
||||
@@ -151,9 +152,9 @@ const DatasetParamsModal = ({
|
||||
min={100}
|
||||
max={maxTokens}
|
||||
step={50}
|
||||
value={getValues(ModuleInputKeyEnum.datasetLimit) ?? 1000}
|
||||
value={getValues(ModuleInputKeyEnum.datasetMaxTokens) ?? 1000}
|
||||
onChange={(val) => {
|
||||
setValue(ModuleInputKeyEnum.datasetLimit, val);
|
||||
setValue(ModuleInputKeyEnum.datasetMaxTokens, val);
|
||||
setRefresh(!refresh);
|
||||
}}
|
||||
/>
|
||||
@@ -161,7 +162,7 @@ const DatasetParamsModal = ({
|
||||
</Box>
|
||||
)}
|
||||
{showSimilarity && (
|
||||
<Box display={['block', 'flex']} py={8}>
|
||||
<Box display={['block', 'flex']} mt={5}>
|
||||
<Box flex={'0 0 120px'} mb={[8, 0]}>
|
||||
{t('core.dataset.search.Min Similarity')}
|
||||
<MyTooltip label={t('core.dataset.search.Min Similarity Tips')} forceShow>
|
||||
|
@@ -12,7 +12,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import type { SelectedDatasetType } from '@fastgpt/global/core/module/api.d';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
|
@@ -66,7 +66,7 @@ const ChatTest = (
|
||||
appName: `调试-${app.name}`
|
||||
},
|
||||
onMessage: generatingMessage,
|
||||
abortSignal: controller
|
||||
abortCtrl: controller
|
||||
});
|
||||
|
||||
return { responseText, responseData };
|
||||
|
@@ -24,7 +24,7 @@ import React, {
|
||||
} from 'react';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
import { appModule2FlowEdge, appModule2FlowNode } from '@/utils/adapt';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { EDGE_TYPE, FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleIOValueTypeEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
||||
import { Textarea, Button, ModalBody, ModalFooter } from '@chakra-ui/react';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useFlowProviderStore } from './FlowProvider';
|
||||
|
||||
type Props = {
|
||||
|
@@ -15,7 +15,7 @@ const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
|
||||
import EmptyTip from '@/components/EmptyTip';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { getPreviewPluginModule } from '@/web/core/plugin/api';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { moduleTemplatesList } from '@/web/core/modules/template/system';
|
||||
|
||||
@@ -100,6 +100,7 @@ const RenderList = React.memo(function RenderList({ templates, onClose }: Render
|
||||
if (template.flowType === FlowNodeTypeEnum.pluginModule) {
|
||||
setLoading(true);
|
||||
const res = await getPreviewPluginModule(template.id);
|
||||
|
||||
setLoading(false);
|
||||
return res;
|
||||
}
|
||||
@@ -107,7 +108,7 @@ const RenderList = React.memo(function RenderList({ templates, onClose }: Render
|
||||
} catch (e) {
|
||||
toast({
|
||||
status: 'error',
|
||||
title: getErrText(e, t('plugin.Get Plugin Module Detail Failed'))
|
||||
title: getErrText(e, t('core.plugin.Get Plugin Module Detail Failed'))
|
||||
});
|
||||
setLoading(false);
|
||||
return Promise.reject(e);
|
||||
|
@@ -1,10 +1,11 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { BezierEdge, getBezierPath, EdgeLabelRenderer, EdgeProps } from 'reactflow';
|
||||
import { onDelConnect } from '../../FlowProvider';
|
||||
import { onDelConnect, useFlowProviderStore } from '../../FlowProvider';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
||||
const ButtonEdge = (props: EdgeProps) => {
|
||||
const { nodes } = useFlowProviderStore();
|
||||
const {
|
||||
id,
|
||||
sourceX,
|
||||
@@ -17,6 +18,13 @@ const ButtonEdge = (props: EdgeProps) => {
|
||||
style = {}
|
||||
} = props;
|
||||
|
||||
const active = (() => {
|
||||
const connectNode = nodes.find((node) => {
|
||||
return (node.id === props.source || node.id === props.target) && node.selected;
|
||||
});
|
||||
return !!(connectNode || selected);
|
||||
})();
|
||||
|
||||
const [, labelX, labelY] = getBezierPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
@@ -41,8 +49,9 @@ const ButtonEdge = (props: EdgeProps) => {
|
||||
borderRadius={'20px'}
|
||||
color={'black'}
|
||||
cursor={'pointer'}
|
||||
border={'1px solid #fff'}
|
||||
zIndex={selected ? 1000 : 0}
|
||||
borderWidth={'1px'}
|
||||
borderColor={'borderColor.low'}
|
||||
zIndex={active ? 1000 : 0}
|
||||
_hover={{
|
||||
boxShadow: '0 0 6px 2px rgba(0, 0, 0, 0.08)'
|
||||
}}
|
||||
@@ -51,26 +60,43 @@ const ButtonEdge = (props: EdgeProps) => {
|
||||
<MyIcon
|
||||
name="closeSolid"
|
||||
w={'100%'}
|
||||
color={selected ? 'primary.700' : 'myGray.500'}
|
||||
color={active ? 'primary.800' : 'myGray.400'}
|
||||
></MyIcon>
|
||||
</Flex>
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
justifyContent={'center'}
|
||||
position={'absolute'}
|
||||
transform={`translate(-78%, -50%) translate(${targetX}px,${targetY}px)`}
|
||||
pointerEvents={'all'}
|
||||
w={'16px'}
|
||||
h={'16px'}
|
||||
bg={'white'}
|
||||
zIndex={active ? 1000 : 0}
|
||||
>
|
||||
<MyIcon
|
||||
name={'common/rightArrowLight'}
|
||||
w={'100%'}
|
||||
color={active ? 'primary.800' : 'myGray.400'}
|
||||
></MyIcon>
|
||||
</Flex>
|
||||
</EdgeLabelRenderer>
|
||||
);
|
||||
}, [id, labelX, labelY, selected]);
|
||||
}, [id, labelX, labelY, active, targetX, targetY]);
|
||||
|
||||
const memoBezierEdge = useMemo(() => {
|
||||
const edgeStyle: React.CSSProperties = {
|
||||
...style,
|
||||
...(selected
|
||||
...(active
|
||||
? {
|
||||
strokeWidth: 4,
|
||||
strokeWidth: 5,
|
||||
stroke: '#3370ff'
|
||||
}
|
||||
: { strokeWidth: 2, stroke: '#BDC1C5' })
|
||||
: { strokeWidth: 2, zIndex: 2, stroke: 'myGray.300' })
|
||||
};
|
||||
|
||||
return <BezierEdge {...props} style={edgeStyle} />;
|
||||
}, [props, selected, style]);
|
||||
}, [props, active, style]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@@ -2,19 +2,22 @@ import React from 'react';
|
||||
import { Box, useTheme } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
const Divider = ({ text }: { text: 'Input' | 'Output' | string }) => {
|
||||
const Divider = ({ text }: { text?: 'Input' | 'Output' | string }) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const isDivider = !text;
|
||||
|
||||
return (
|
||||
<Box
|
||||
textAlign={'center'}
|
||||
bg={'#f8f8f8'}
|
||||
py={2}
|
||||
py={isDivider ? '0' : 2}
|
||||
borderTop={theme.borders.base}
|
||||
borderBottom={theme.borders.base}
|
||||
fontSize={'lg'}
|
||||
>
|
||||
{t(`common.${text}`)}
|
||||
{text ? t(`common.${text}`) : ''}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@@ -8,7 +8,7 @@ import MySelect from '@/components/Select';
|
||||
import { TTSTypeEnum } from '@/constants/app';
|
||||
import type { AppTTSConfigType } from '@fastgpt/global/core/module/type.d';
|
||||
import { useAudioPlay } from '@/web/common/utils/voice';
|
||||
import { audioSpeechModelList } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import MySlider from '@/components/Slider';
|
||||
|
||||
@@ -20,6 +20,7 @@ const TTSSelect = ({
|
||||
onChange: (e: AppTTSConfigType) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { audioSpeechModelList } = useSystemStore();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
const list = useMemo(
|
||||
@@ -28,7 +29,7 @@ const TTSSelect = ({
|
||||
{ label: t('core.app.tts.Web'), value: TTSTypeEnum.web },
|
||||
...audioSpeechModelList.map((item) => item?.voices || []).flat()
|
||||
],
|
||||
[t]
|
||||
[audioSpeechModelList, t]
|
||||
);
|
||||
|
||||
const formatValue = useMemo(() => {
|
||||
@@ -106,7 +107,7 @@ const TTSSelect = ({
|
||||
{t('core.app.tts.Speech model')}
|
||||
<MySelect w={'220px'} value={formatValue} list={list} onchange={onclickChange} />
|
||||
</Flex>
|
||||
<Flex mt={8} justifyContent={'space-between'} alignItems={'center'}>
|
||||
<Flex mt={8} justifyContent={'space-between'}>
|
||||
{t('core.app.tts.Speech speed')}
|
||||
<MySlider
|
||||
markList={[
|
||||
|
@@ -36,9 +36,9 @@ import MyModal from '@/components/MyModal';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { variableTip } from '@fastgpt/global/core/module/template/tip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import MyRadio from '@/components/common/MyRadio';
|
||||
import { formatVariablesIcon } from '@fastgpt/global/core/module/utils';
|
||||
import { formatEditorVariablePickerIcon } from '@fastgpt/global/core/module/utils';
|
||||
|
||||
const VariableEdit = ({
|
||||
variables,
|
||||
@@ -102,7 +102,14 @@ const VariableEdit = ({
|
||||
};
|
||||
|
||||
const formatVariables = useMemo(() => {
|
||||
return formatVariablesIcon(variables);
|
||||
const results = formatEditorVariablePickerIcon(variables);
|
||||
return results.map((item) => {
|
||||
const variable = variables.find((variable) => variable.key === item.key);
|
||||
return {
|
||||
...variable,
|
||||
icon: item.icon
|
||||
};
|
||||
});
|
||||
}, [variables]);
|
||||
|
||||
return (
|
||||
@@ -111,7 +118,7 @@ const VariableEdit = ({
|
||||
<MyIcon name={'core/app/simpleMode/variable'} w={'20px'} />
|
||||
<Box ml={2} flex={1}>
|
||||
{t('core.module.Variable')}
|
||||
<MyTooltip label={variableTip} forceShow>
|
||||
<MyTooltip label={t(variableTip)} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
</Box>
|
||||
|
@@ -6,17 +6,16 @@ import Container from '../modules/Container';
|
||||
import RenderInput from '../render/RenderInput';
|
||||
import RenderOutput from '../render/RenderOutput';
|
||||
|
||||
const NodeAnswer = React.memo(function NodeAnswer({ data }: { data: FlowModuleItemType }) {
|
||||
const NodeAnswer = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
const { moduleId, inputs, outputs } = data;
|
||||
|
||||
return (
|
||||
<NodeCard minW={'400px'} {...data}>
|
||||
<NodeCard minW={'400px'} selected={selected} {...data}>
|
||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||
<RenderInput moduleId={moduleId} flowInputList={inputs} />
|
||||
<RenderOutput moduleId={moduleId} flowOutputList={outputs} />
|
||||
</Container>
|
||||
</NodeCard>
|
||||
);
|
||||
});
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodeAnswer data={data} />;
|
||||
}
|
||||
};
|
||||
export default React.memo(NodeAnswer);
|
||||
|
@@ -17,12 +17,12 @@ import SourceHandle from '../render/SourceHandle';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { onChangeNode } from '../../FlowProvider';
|
||||
|
||||
const NodeCQNode = React.memo(function NodeCQNode({ data }: { data: FlowModuleItemType }) {
|
||||
const NodeCQNode = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
const { t } = useTranslation();
|
||||
const { moduleId, inputs } = data;
|
||||
|
||||
return (
|
||||
<NodeCard minW={'400px'} {...data}>
|
||||
<NodeCard minW={'400px'} selected={selected} {...data}>
|
||||
<Divider text="Input" />
|
||||
<Container>
|
||||
<RenderInput
|
||||
@@ -136,7 +136,5 @@ const NodeCQNode = React.memo(function NodeCQNode({ data }: { data: FlowModuleIt
|
||||
</Container>
|
||||
</NodeCard>
|
||||
);
|
||||
});
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodeCQNode data={data} />;
|
||||
}
|
||||
};
|
||||
export default React.memo(NodeCQNode);
|
||||
|
@@ -0,0 +1,145 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { NodeProps } from 'reactflow';
|
||||
import NodeCard from '../render/NodeCard';
|
||||
import { FlowModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||
import Container from '../modules/Container';
|
||||
import RenderInput from '../render/RenderInput';
|
||||
import { Box, Button, Flex } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { AddIcon } from '@chakra-ui/icons';
|
||||
import {
|
||||
ModuleIOValueTypeEnum,
|
||||
ModuleInputKeyEnum,
|
||||
ModuleOutputKeyEnum
|
||||
} from '@fastgpt/global/core/module/constants';
|
||||
import { getOneQuoteInputTemplate } from '@fastgpt/global/core/module/template/system/datasetConcat';
|
||||
import { onChangeNode, useFlowProviderStore } from '../../FlowProvider';
|
||||
import TargetHandle from '../render/TargetHandle';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import SourceHandle from '../render/SourceHandle';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import MySlider from '@/components/Slider';
|
||||
|
||||
const NodeDatasetConcat = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
const { t } = useTranslation();
|
||||
const { llmModelList } = useSystemStore();
|
||||
const { nodes } = useFlowProviderStore();
|
||||
const { moduleId, inputs, outputs } = data;
|
||||
|
||||
const quotes = inputs.filter((item) => item.valueType === ModuleIOValueTypeEnum.datasetQuote);
|
||||
|
||||
const tokenLimit = useMemo(() => {
|
||||
let maxTokens = 3000;
|
||||
|
||||
nodes.forEach((item) => {
|
||||
if (item.type === FlowNodeTypeEnum.chatNode) {
|
||||
const model =
|
||||
item.data.inputs.find((item) => item.key === ModuleInputKeyEnum.aiModel)?.value || '';
|
||||
const quoteMaxToken =
|
||||
llmModelList.find((item) => item.model === model)?.quoteMaxToken || 3000;
|
||||
|
||||
maxTokens = Math.max(maxTokens, quoteMaxToken);
|
||||
}
|
||||
});
|
||||
|
||||
return maxTokens;
|
||||
}, [llmModelList, nodes]);
|
||||
|
||||
const RenderQuoteList = useMemo(
|
||||
() => (
|
||||
<Box>
|
||||
<Box>
|
||||
{quotes.map((quote, i) => (
|
||||
<Flex key={quote.key} position={'relative'} mb={4} alignItems={'center'}>
|
||||
<TargetHandle handleKey={quote.key} valueType={quote.valueType} />
|
||||
<Box>
|
||||
{t('core.chat.Quote')}
|
||||
{i + 1}
|
||||
</Box>
|
||||
<MyIcon
|
||||
ml={2}
|
||||
w={'14px'}
|
||||
name={'delete'}
|
||||
cursor={'pointer'}
|
||||
_hover={{ color: 'red.600' }}
|
||||
onClick={() => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'delInput',
|
||||
key: quote.key
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
))}
|
||||
</Box>
|
||||
<Button
|
||||
leftIcon={<AddIcon />}
|
||||
variant={'whiteBase'}
|
||||
onClick={() => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'addInput',
|
||||
value: getOneQuoteInputTemplate()
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t('core.module.Dataset quote.Add quote')}
|
||||
</Button>
|
||||
</Box>
|
||||
),
|
||||
[moduleId, quotes, t]
|
||||
);
|
||||
|
||||
return (
|
||||
<NodeCard minW={'400px'} selected={selected} {...data}>
|
||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'} position={'relative'}>
|
||||
<RenderInput
|
||||
moduleId={moduleId}
|
||||
flowInputList={inputs}
|
||||
CustomComponent={{
|
||||
[ModuleInputKeyEnum.datasetMaxTokens]: (item) => (
|
||||
<Box px={2}>
|
||||
<MySlider
|
||||
markList={[
|
||||
{ label: '100', value: 100 },
|
||||
{ label: tokenLimit, value: tokenLimit }
|
||||
]}
|
||||
width={'100%'}
|
||||
min={100}
|
||||
max={tokenLimit}
|
||||
step={50}
|
||||
value={item.value}
|
||||
onChange={(e) => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'updateInput',
|
||||
key: item.key,
|
||||
value: {
|
||||
...item,
|
||||
value: e
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
{/* render dataset select */}
|
||||
{RenderQuoteList}
|
||||
<Flex position={'absolute'} right={4} top={'50%'} transform={'translate(0,-50%)'}>
|
||||
<Box>{t('core.module.Dataset quote.Concat result')}</Box>
|
||||
<SourceHandle
|
||||
handleKey={ModuleOutputKeyEnum.datasetQuoteQA}
|
||||
valueType={ModuleIOValueTypeEnum.datasetQuote}
|
||||
// transform={'translate(-14px, -50%)'}
|
||||
/>
|
||||
</Flex>
|
||||
{/* <RenderOutput moduleId={moduleId} flowOutputList={outputs} /> */}
|
||||
</Container>
|
||||
</NodeCard>
|
||||
);
|
||||
};
|
||||
export default React.memo(NodeDatasetConcat);
|
@@ -3,10 +3,8 @@ import { NodeProps } from 'reactflow';
|
||||
import NodeCard from '../render/NodeCard';
|
||||
import { FlowModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||
|
||||
const NodeAnswer = React.memo(function NodeAnswer({ data }: { data: FlowModuleItemType }) {
|
||||
return <NodeCard {...data}></NodeCard>;
|
||||
});
|
||||
const NodeEmpty = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
return <NodeCard selected={selected} {...data}></NodeCard>;
|
||||
};
|
||||
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodeAnswer data={data} />;
|
||||
}
|
||||
export default React.memo(NodeEmpty);
|
||||
|
@@ -17,7 +17,7 @@ import { FlowNodeOutputTypeEnum } from '@fastgpt/global/core/module/node/constan
|
||||
import { ModuleIOValueTypeEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { onChangeNode } from '../../../FlowProvider';
|
||||
|
||||
const NodeExtract = React.memo(function NodeExtract({ data }: { data: FlowModuleItemType }) {
|
||||
const NodeExtract = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||
const { inputs, outputs, moduleId } = data;
|
||||
const { t } = useTranslation();
|
||||
const [editExtractFiled, setEditExtractField] = useState<ContextExtractAgentItemType>();
|
||||
@@ -183,8 +183,6 @@ const NodeExtract = React.memo(function NodeExtract({ data }: { data: FlowModule
|
||||
)}
|
||||
</NodeCard>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodeExtract data={data} />;
|
||||
}
|
||||
export default React.memo(NodeExtract);
|
||||
|
@@ -1,37 +0,0 @@
|
||||
import React from 'react';
|
||||
import { NodeProps } from 'reactflow';
|
||||
import NodeCard from '../render/NodeCard';
|
||||
import { FlowModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||
import Divider from '../modules/Divider';
|
||||
import Container from '../modules/Container';
|
||||
import RenderInput from '../render/RenderInput';
|
||||
import { Box, Button } from '@chakra-ui/react';
|
||||
import { SmallAddIcon } from '@chakra-ui/icons';
|
||||
import RenderOutput from '../render/RenderOutput';
|
||||
|
||||
import {
|
||||
FlowNodeInputTypeEnum,
|
||||
FlowNodeOutputTypeEnum
|
||||
} from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleIOValueTypeEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
|
||||
|
||||
const NodeHttp = React.memo(function NodeHttp({ data }: { data: FlowModuleItemType }) {
|
||||
const { moduleId, inputs, outputs } = data;
|
||||
|
||||
return (
|
||||
<NodeCard minW={'350px'} {...data}>
|
||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||
<RenderInput moduleId={moduleId} flowInputList={inputs} />
|
||||
</Container>
|
||||
<Divider text="Output" />
|
||||
<Container>
|
||||
<RenderOutput moduleId={moduleId} flowOutputList={outputs} />
|
||||
</Container>
|
||||
</NodeCard>
|
||||
);
|
||||
});
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodeHttp data={data} />;
|
||||
}
|
@@ -41,18 +41,14 @@ const createEditField = {
|
||||
inputType: true
|
||||
};
|
||||
|
||||
const NodePluginInput = React.memo(function NodePluginInput({
|
||||
data
|
||||
}: {
|
||||
data: FlowModuleItemType;
|
||||
}) {
|
||||
const NodePluginInput = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
const { t } = useTranslation();
|
||||
const { moduleId, inputs, outputs } = data;
|
||||
const [createField, setCreateField] = useState<EditNodeFieldType>();
|
||||
const [editField, setEditField] = useState<EditNodeFieldType>();
|
||||
|
||||
return (
|
||||
<NodeCard minW={'300px'} {...data}>
|
||||
<NodeCard minW={'300px'} selected={selected} forbidMenu {...data}>
|
||||
<Container mt={1} borderTop={'2px solid'} borderTopColor={'myGray.300'}>
|
||||
{inputs.map((item) => (
|
||||
<Flex
|
||||
@@ -257,7 +253,5 @@ const NodePluginInput = React.memo(function NodePluginInput({
|
||||
)}
|
||||
</NodeCard>
|
||||
);
|
||||
});
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodePluginInput data={data} />;
|
||||
}
|
||||
};
|
||||
export default React.memo(NodePluginInput);
|
||||
|
@@ -14,7 +14,7 @@ import Container from '../modules/Container';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import TargetHandle from '../render/TargetHandle';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import {
|
||||
EditNodeFieldType,
|
||||
FlowNodeInputItemType,
|
||||
@@ -42,18 +42,14 @@ const createEditField = {
|
||||
inputType: false
|
||||
};
|
||||
|
||||
const NodePluginOutput = React.memo(function NodePluginOutput({
|
||||
data
|
||||
}: {
|
||||
data: FlowModuleItemType;
|
||||
}) {
|
||||
const NodePluginOutput = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
const { t } = useTranslation();
|
||||
const { moduleId, inputs, outputs } = data;
|
||||
const [createField, setCreateField] = useState<EditNodeFieldType>();
|
||||
const [editField, setEditField] = useState<EditNodeFieldType>();
|
||||
|
||||
return (
|
||||
<NodeCard minW={'300px'} {...data}>
|
||||
<NodeCard minW={'300px'} selected={selected} forbidMenu {...data}>
|
||||
<Container mt={1} borderTop={'2px solid'} borderTopColor={'myGray.300'}>
|
||||
{inputs.map((item) => (
|
||||
<Flex
|
||||
@@ -237,8 +233,6 @@ const NodePluginOutput = React.memo(function NodePluginOutput({
|
||||
)}
|
||||
</NodeCard>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodePluginOutput data={data} />;
|
||||
}
|
||||
export default React.memo(NodePluginOutput);
|
||||
|
@@ -6,22 +6,16 @@ import Container from '../modules/Container';
|
||||
|
||||
import RenderOutput from '../render/RenderOutput';
|
||||
|
||||
const QuestionInputNode = React.memo(function QuestionInputNode({
|
||||
data
|
||||
}: {
|
||||
data: FlowModuleItemType;
|
||||
}) {
|
||||
const QuestionInputNode = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
const { moduleId, outputs } = data;
|
||||
|
||||
return (
|
||||
<NodeCard minW={'240px'} {...data}>
|
||||
<NodeCard minW={'240px'} selected={selected} {...data}>
|
||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'} textAlign={'end'}>
|
||||
<RenderOutput moduleId={moduleId} flowOutputList={outputs} />
|
||||
</Container>
|
||||
</NodeCard>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <QuestionInputNode data={data} />;
|
||||
}
|
||||
export default React.memo(QuestionInputNode);
|
||||
|
@@ -7,11 +7,11 @@ import Container from '../modules/Container';
|
||||
import RenderInput from '../render/RenderInput';
|
||||
import RenderOutput from '../render/RenderOutput';
|
||||
|
||||
const NodeRunAPP = React.memo(function NodeRunAPP({ data }: { data: FlowModuleItemType }) {
|
||||
const NodeRunAPP = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
const { moduleId, inputs, outputs } = data;
|
||||
|
||||
return (
|
||||
<NodeCard minW={'350px'} {...data}>
|
||||
<NodeCard minW={'350px'} selected={selected} {...data}>
|
||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||
<RenderInput moduleId={moduleId} flowInputList={inputs} />
|
||||
</Container>
|
||||
@@ -21,7 +21,5 @@ const NodeRunAPP = React.memo(function NodeRunAPP({ data }: { data: FlowModuleIt
|
||||
</Container>
|
||||
</NodeCard>
|
||||
);
|
||||
});
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodeRunAPP data={data} />;
|
||||
}
|
||||
};
|
||||
export default React.memo(NodeRunAPP);
|
||||
|
@@ -7,11 +7,11 @@ import Container from '../modules/Container';
|
||||
import RenderInput from '../render/RenderInput';
|
||||
import RenderOutput from '../render/RenderOutput';
|
||||
|
||||
const NodeSimple = React.memo(function NodeSimple({ data }: { data: FlowModuleItemType }) {
|
||||
const NodeSimple = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
const { moduleId, inputs, outputs } = data;
|
||||
|
||||
return (
|
||||
<NodeCard minW={'350px'} {...data}>
|
||||
<NodeCard minW={'350px'} selected={selected} {...data}>
|
||||
{inputs.length > 0 && (
|
||||
<>
|
||||
<Divider text="Input" />
|
||||
@@ -30,7 +30,5 @@ const NodeSimple = React.memo(function NodeSimple({ data }: { data: FlowModuleIt
|
||||
)}
|
||||
</NodeCard>
|
||||
);
|
||||
});
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodeSimple data={data} />;
|
||||
}
|
||||
};
|
||||
export default React.memo(NodeSimple);
|
||||
|
@@ -18,11 +18,11 @@ import TTSSelect from '@/components/core/module/Flow/components/modules/TTSSelec
|
||||
import { splitGuideModule } from '@fastgpt/global/core/module/utils';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
const NodeUserGuide = React.memo(function NodeUserGuide({ data }: { data: FlowModuleItemType }) {
|
||||
const NodeUserGuide = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<>
|
||||
<NodeCard minW={'300px'} {...data}>
|
||||
<NodeCard minW={'300px'} selected={selected} {...data}>
|
||||
<Container className="nodrag" borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||
<WelcomeText data={data} />
|
||||
<Box pt={4} pb={2}>
|
||||
@@ -38,12 +38,11 @@ const NodeUserGuide = React.memo(function NodeUserGuide({ data }: { data: FlowMo
|
||||
</NodeCard>
|
||||
</>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
|
||||
return <NodeUserGuide data={data} />;
|
||||
}
|
||||
export function WelcomeText({ data }: { data: FlowModuleItemType }) {
|
||||
export default React.memo(NodeUserGuide);
|
||||
|
||||
function WelcomeText({ data }: { data: FlowModuleItemType }) {
|
||||
const { t } = useTranslation();
|
||||
const { inputs, moduleId } = data;
|
||||
const [, startTst] = useTransition();
|
||||
|
@@ -20,7 +20,7 @@ import {
|
||||
FlowNodeOutputTypeEnum
|
||||
} from '@fastgpt/global/core/module/node/constant';
|
||||
import { EditInputFieldMap, EditNodeFieldType } from '@fastgpt/global/core/module/node/type.d';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const FieldEditModal = ({
|
||||
editField = {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { Box, Flex, useTheme, Menu, MenuButton, MenuList, MenuItem } from '@chakra-ui/react';
|
||||
import { Box, Flex, useTheme, MenuButton } from '@chakra-ui/react';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import type { FlowModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||
@@ -7,7 +7,7 @@ import MyTooltip from '@/components/MyTooltip';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { onChangeNode, onCopyNode, onResetNode, onDelNode } from '../../FlowProvider';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
@@ -16,11 +16,13 @@ import { getPreviewPluginModule } from '@/web/core/plugin/api';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { LOGO_ICON } from '@fastgpt/global/common/system/constants';
|
||||
import MyMenu from '@/components/MyMenu';
|
||||
|
||||
type Props = FlowModuleItemType & {
|
||||
children?: React.ReactNode | React.ReactNode[] | string;
|
||||
minW?: string | number;
|
||||
isPreview?: boolean;
|
||||
forbidMenu?: boolean;
|
||||
selected?: boolean;
|
||||
};
|
||||
|
||||
const NodeCard = (props: Props) => {
|
||||
@@ -34,7 +36,8 @@ const NodeCard = (props: Props) => {
|
||||
moduleId,
|
||||
flowType,
|
||||
inputs,
|
||||
isPreview
|
||||
selected,
|
||||
forbidMenu
|
||||
} = props;
|
||||
|
||||
const theme = useTheme();
|
||||
@@ -113,12 +116,6 @@ const NodeCard = (props: Props) => {
|
||||
icon: 'delete',
|
||||
label: t('common.Delete'),
|
||||
onClick: () => onDelNode(moduleId)
|
||||
},
|
||||
|
||||
{
|
||||
icon: 'common/backLight',
|
||||
label: t('common.Back'),
|
||||
onClick: () => {}
|
||||
}
|
||||
],
|
||||
[flowType, inputs, moduleId, name, onOpenModal, openConfirm, setLoading, t, toast]
|
||||
@@ -129,13 +126,16 @@ const NodeCard = (props: Props) => {
|
||||
minW={minW}
|
||||
maxW={'500px'}
|
||||
bg={'white'}
|
||||
border={theme.borders.md}
|
||||
borderWidth={'1px'}
|
||||
borderColor={selected ? 'primary.600' : 'borderColor.base'}
|
||||
borderRadius={'md'}
|
||||
boxShadow={'sm'}
|
||||
className={isPreview ? 'nodrag' : ''}
|
||||
boxShadow={'1'}
|
||||
_hover={{
|
||||
boxShadow: '4'
|
||||
}}
|
||||
>
|
||||
<Flex className="custom-drag-handle" px={4} py={3} alignItems={'center'}>
|
||||
<Avatar src={avatar} borderRadius={'md'} objectFit={'contain'} w={'30px'} h={'30px'} />
|
||||
<Avatar src={avatar} borderRadius={'0'} objectFit={'contain'} w={'30px'} h={'30px'} />
|
||||
<Box ml={3} fontSize={'lg'} color={'myGray.600'}>
|
||||
{t(name)}
|
||||
</Box>
|
||||
@@ -145,28 +145,25 @@ const NodeCard = (props: Props) => {
|
||||
</MyTooltip>
|
||||
)}
|
||||
<Box flex={1} />
|
||||
{!isPreview && (
|
||||
<Menu autoSelect={false} isLazy>
|
||||
<MenuButton
|
||||
className={'nodrag'}
|
||||
_hover={{ bg: 'myWhite.600' }}
|
||||
cursor={'pointer'}
|
||||
borderRadius={'md'}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MyIcon name={'more'} w={'14px'} p={2} />
|
||||
</MenuButton>
|
||||
<MenuList color={'myGray.700'} minW={`120px !important`} zIndex={10}>
|
||||
{menuList.map((item) => (
|
||||
<MenuItem key={item.label} onClick={item.onClick} py={[2, 3]}>
|
||||
<MyIcon name={item.icon as any} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{item.label}</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
</Menu>
|
||||
{!forbidMenu && (
|
||||
<MyMenu
|
||||
offset={[-60, 5]}
|
||||
width={120}
|
||||
Button={
|
||||
<MenuButton
|
||||
className={'nodrag'}
|
||||
_hover={{ bg: 'myWhite.600' }}
|
||||
cursor={'pointer'}
|
||||
borderRadius={'md'}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MyIcon name={'more'} w={'14px'} p={2} />
|
||||
</MenuButton>
|
||||
}
|
||||
menuList={menuList}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
{children}
|
||||
|
@@ -123,25 +123,21 @@ const RenderInput = ({ flowInputList, moduleId, CustomComponent }: Props) => {
|
||||
return <Component inputs={filterInputs} item={input} moduleId={moduleId} />;
|
||||
})();
|
||||
|
||||
return (
|
||||
return input.type !== FlowNodeInputTypeEnum.hidden ? (
|
||||
<Box key={input.key} _notLast={{ mb: 7 }} position={'relative'}>
|
||||
{input.key === ModuleInputKeyEnum.userChatInput && (
|
||||
<UserChatInput inputs={filterInputs} item={input} moduleId={moduleId} />
|
||||
)}
|
||||
{input.type !== FlowNodeInputTypeEnum.hidden && (
|
||||
<>
|
||||
{!!input.label && (
|
||||
<InputLabel moduleId={moduleId} inputKey={input.key} mode={mode} {...input} />
|
||||
)}
|
||||
{!!RenderComponent && (
|
||||
<Box mt={2} className={'nodrag'}>
|
||||
{RenderComponent}
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
{!!input.label && (
|
||||
<InputLabel moduleId={moduleId} inputKey={input.key} mode={mode} {...input} />
|
||||
)}
|
||||
{!!RenderComponent && (
|
||||
<Box mt={2} className={'nodrag'}>
|
||||
{RenderComponent}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
) : null;
|
||||
});
|
||||
}, [memoCustomComponent, filterInputs, mode, moduleId]);
|
||||
|
||||
|
@@ -2,17 +2,11 @@ import React, { useCallback, useEffect } from 'react';
|
||||
import type { RenderInputProps } from '../type';
|
||||
import { onChangeNode } from '../../../../FlowProvider';
|
||||
import SelectAiModel from '@/components/Select/SelectAiModel';
|
||||
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { chatModelList, cqModelList, extractModelList } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
const SelectAiModelRender = ({ item, inputs = [], moduleId }: RenderInputProps) => {
|
||||
const modelList = (() => {
|
||||
if (item.type === FlowNodeInputTypeEnum.selectChatModel) return chatModelList;
|
||||
if (item.type === FlowNodeInputTypeEnum.selectCQModel) return cqModelList;
|
||||
if (item.type === FlowNodeInputTypeEnum.selectExtractModel) return extractModelList;
|
||||
|
||||
return [];
|
||||
})().map((item) => ({
|
||||
const { llmModelList } = useSystemStore();
|
||||
const modelList = llmModelList.map((item) => ({
|
||||
model: item.model,
|
||||
name: item.name,
|
||||
maxResponse: item.maxResponse
|
||||
|
@@ -10,7 +10,7 @@ import { useTranslation } from 'next-i18next';
|
||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { chatModelList } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
@@ -21,6 +21,7 @@ const DatasetParamsModal = dynamic(() => import('@/components/core/module/Datase
|
||||
const SelectDatasetRender = ({ inputs = [], item, moduleId }: RenderInputProps) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const { llmModelList } = useSystemStore();
|
||||
const [nodes, setNodes] = useState<useFlowProviderStoreType['nodes']>([]);
|
||||
const [data, setData] = useState({
|
||||
searchMode: DatasetSearchModeEnum.embedding,
|
||||
@@ -49,7 +50,7 @@ const SelectDatasetRender = ({ inputs = [], item, moduleId }: RenderInputProps)
|
||||
const model =
|
||||
item.data.inputs.find((item) => item.key === ModuleInputKeyEnum.aiModel)?.value || '';
|
||||
const quoteMaxToken =
|
||||
chatModelList.find((item) => item.model === model)?.quoteMaxToken || 3000;
|
||||
llmModelList.find((item) => item.model === model)?.quoteMaxToken || 3000;
|
||||
|
||||
maxTokens = Math.max(maxTokens, quoteMaxToken);
|
||||
}
|
||||
|
@@ -6,14 +6,15 @@ import { useTranslation } from 'next-i18next';
|
||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { chatModelList } from '@/web/common/system/staticData';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import DatasetParamsModal from '@/components/core/module/DatasetParamsModal';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
const SelectDatasetParam = ({ inputs = [], moduleId }: RenderInputProps) => {
|
||||
const { nodes } = useFlowProviderStore();
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { llmModelList } = useSystemStore();
|
||||
const [data, setData] = useState({
|
||||
searchMode: DatasetSearchModeEnum.embedding,
|
||||
limit: 5,
|
||||
@@ -29,14 +30,14 @@ const SelectDatasetParam = ({ inputs = [], moduleId }: RenderInputProps) => {
|
||||
const model =
|
||||
item.data.inputs.find((item) => item.key === ModuleInputKeyEnum.aiModel)?.value || '';
|
||||
const quoteMaxToken =
|
||||
chatModelList.find((item) => item.model === model)?.quoteMaxToken || 3000;
|
||||
llmModelList.find((item) => item.model === model)?.quoteMaxToken || 3000;
|
||||
|
||||
maxTokens = Math.max(maxTokens, quoteMaxToken);
|
||||
}
|
||||
});
|
||||
|
||||
return maxTokens;
|
||||
}, [nodes]);
|
||||
}, [llmModelList, nodes]);
|
||||
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
|
@@ -8,7 +8,7 @@ import MySlider from '@/components/Slider';
|
||||
const SliderRender = ({ item, moduleId }: RenderInputProps) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Box pt={5} pb={4} px={2}>
|
||||
<Box px={2}>
|
||||
<MySlider
|
||||
markList={item.markList}
|
||||
width={'100%'}
|
||||
|
@@ -4,37 +4,42 @@ import { useFlowProviderStore, onChangeNode } from '../../../../FlowProvider';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
|
||||
import {
|
||||
formatVariablesIcon,
|
||||
formatEditorVariablePickerIcon,
|
||||
getGuideModule,
|
||||
splitGuideModule
|
||||
} from '@fastgpt/global/core/module/utils';
|
||||
|
||||
const TextareaRender = ({ item, moduleId }: RenderInputProps) => {
|
||||
const TextareaRender = ({ inputs = [], item, moduleId }: RenderInputProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [, startTst] = useTransition();
|
||||
const { nodes } = useFlowProviderStore();
|
||||
|
||||
// get variable
|
||||
const variables = useMemo(
|
||||
() =>
|
||||
formatVariablesIcon(
|
||||
splitGuideModule(getGuideModule(nodes.map((node) => node.data)))?.variableModules || []
|
||||
),
|
||||
[nodes]
|
||||
);
|
||||
const variables = useMemo(() => {
|
||||
const globalVariables = formatEditorVariablePickerIcon(
|
||||
splitGuideModule(getGuideModule(nodes.map((node) => node.data)))?.variableModules || []
|
||||
);
|
||||
const moduleVariables = formatEditorVariablePickerIcon(
|
||||
inputs
|
||||
.filter((input) => input.edit)
|
||||
.map((item) => ({
|
||||
key: item.key,
|
||||
label: item.label
|
||||
}))
|
||||
);
|
||||
|
||||
return [...globalVariables, ...moduleVariables];
|
||||
}, [inputs, nodes]);
|
||||
|
||||
const onChange = useCallback(
|
||||
(e: string) => {
|
||||
startTst(() => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'updateInput',
|
||||
key: item.key,
|
||||
value: {
|
||||
...item,
|
||||
value: e
|
||||
}
|
||||
});
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
type: 'updateInput',
|
||||
key: item.key,
|
||||
value: {
|
||||
...item,
|
||||
value: e
|
||||
}
|
||||
});
|
||||
},
|
||||
[item, moduleId]
|
||||
@@ -46,7 +51,7 @@ const TextareaRender = ({ item, moduleId }: RenderInputProps) => {
|
||||
title={t(item.label)}
|
||||
h={150}
|
||||
placeholder={t(item.placeholder || '')}
|
||||
defaultValue={item.value}
|
||||
value={item.value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
|
@@ -19,6 +19,9 @@ const nodeTypes: Record<`${FlowNodeTypeEnum}`, any> = {
|
||||
[FlowNodeTypeEnum.historyNode]: NodeSimple,
|
||||
[FlowNodeTypeEnum.chatNode]: NodeSimple,
|
||||
[FlowNodeTypeEnum.datasetSearchNode]: NodeSimple,
|
||||
[FlowNodeTypeEnum.datasetConcatNode]: dynamic(
|
||||
() => import('./components/nodes/NodeDatasetConcat')
|
||||
),
|
||||
[FlowNodeTypeEnum.answerNode]: dynamic(() => import('./components/nodes/NodeAnswer')),
|
||||
[FlowNodeTypeEnum.classifyQuestion]: dynamic(() => import('./components/nodes/NodeCQNode')),
|
||||
[FlowNodeTypeEnum.contentExtract]: dynamic(() => import('./components/nodes/NodeExtract')),
|
||||
|
@@ -14,7 +14,7 @@ export const flowNode2Modules = ({
|
||||
const modules: ModuleItemType[] = nodes.map((item) => ({
|
||||
moduleId: item.data.moduleId,
|
||||
name: item.data.name,
|
||||
avatar: item.data.avatar,
|
||||
// avatar: item.data.avatar,
|
||||
flowType: item.data.flowType,
|
||||
showStatus: item.data.showStatus,
|
||||
position: item.position,
|
||||
|
@@ -32,7 +32,7 @@ import { useLoading } from '@/web/common/hooks/useLoading';
|
||||
import dayjs from 'dayjs';
|
||||
import { AddIcon, QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyModal from '@/components/MyModal';
|
||||
@@ -40,6 +40,7 @@ import { useForm } from 'react-hook-form';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { getDocPath } from '@/web/common/system/doc';
|
||||
import MyMenu from '@/components/MyMenu';
|
||||
|
||||
type EditProps = EditApiKeyProps & { _id?: string };
|
||||
const defaultEditData: EditProps = {
|
||||
@@ -54,6 +55,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
const { Loading } = useLoading();
|
||||
const theme = useTheme();
|
||||
const { copyData } = useCopyData();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const [baseUrl, setBaseUrl] = useState('https://fastgpt.in/api');
|
||||
const [editData, setEditData] = useState<EditProps>();
|
||||
const [apiKey, setApiKey] = useState('');
|
||||
@@ -177,35 +179,37 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
: t('common.Un used')}
|
||||
</Td>
|
||||
<Td>
|
||||
<Menu autoSelect={false} isLazy>
|
||||
<MenuButton
|
||||
_hover={{ bg: 'myWhite.600 ' }}
|
||||
cursor={'pointer'}
|
||||
borderRadius={'md'}
|
||||
>
|
||||
<MyIcon name={'more'} w={'14px'} p={2} />
|
||||
</MenuButton>
|
||||
<MenuList color={'myGray.700'} minW={`120px !important`} zIndex={10}>
|
||||
<MenuItem
|
||||
onClick={() =>
|
||||
<MyMenu
|
||||
offset={[-50, 5]}
|
||||
Button={
|
||||
<MyIcon
|
||||
name={'more'}
|
||||
w={'14px'}
|
||||
p={2}
|
||||
_hover={{ bg: 'myWhite.600 ' }}
|
||||
cursor={'pointer'}
|
||||
borderRadius={'md'}
|
||||
/>
|
||||
}
|
||||
menuList={[
|
||||
{
|
||||
label: t('common.Edit'),
|
||||
icon: 'edit',
|
||||
onClick: () =>
|
||||
setEditData({
|
||||
_id,
|
||||
name,
|
||||
limit,
|
||||
appId
|
||||
})
|
||||
}
|
||||
py={[2, 3]}
|
||||
>
|
||||
<MyIcon name={'edit'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('common.Edit')}</Box>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => onclickRemove(_id)} py={[2, 3]}>
|
||||
<MyIcon name={'delete'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('common.Delete')}</Box>
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
},
|
||||
{
|
||||
label: t('common.Delete'),
|
||||
icon: 'delete',
|
||||
onClick: () => onclickRemove(_id)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
@@ -285,6 +289,7 @@ function EditKeyModal({
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const isEdit = useMemo(() => !!defaultData._id, [defaultData]);
|
||||
const { feConfigs } = useSystemStore();
|
||||
|
||||
const {
|
||||
register,
|
||||
|
@@ -3,7 +3,7 @@ import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { compressImgFileAndUpload } from '@/web/common/file/controller';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import MyModal from '@/components/MyModal';
|
||||
|
@@ -42,7 +42,7 @@ import { useLoading } from '@/web/common/hooks/useLoading';
|
||||
import { FormDataType, defaultForm } from './EditModal';
|
||||
import MyMenu from '@/components/MyMenu';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const EditModal = dynamic(() => import('./EditModal'));
|
||||
const InviteModal = dynamic(() => import('./InviteModal'));
|
||||
@@ -324,11 +324,13 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
item.role !== TeamMemberRoleEnum.owner && (
|
||||
<MyMenu
|
||||
width={20}
|
||||
trigger="click"
|
||||
Button={
|
||||
<MenuButton
|
||||
_hover={{
|
||||
bg: 'myWhite.600'
|
||||
}}
|
||||
borderRadius={'md'}
|
||||
px={2}
|
||||
py={1}
|
||||
lineHeight={1}
|
||||
@@ -344,7 +346,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
menuList={[
|
||||
{
|
||||
isActive: item.role === TeamMemberRoleEnum.visitor,
|
||||
child: t('user.team.Invite Role Visitor Tip'),
|
||||
label: t('user.team.Invite Role Visitor Tip'),
|
||||
onClick: () => {
|
||||
onUpdateMember({
|
||||
teamId: item.teamId,
|
||||
@@ -355,7 +357,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
},
|
||||
{
|
||||
isActive: item.role === TeamMemberRoleEnum.admin,
|
||||
child: t('user.team.Invite Role Admin Tip'),
|
||||
label: t('user.team.Invite Role Admin Tip'),
|
||||
onClick: () => {
|
||||
onUpdateMember({
|
||||
teamId: item.teamId,
|
||||
@@ -367,7 +369,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
...(item.status === TeamMemberStatusEnum.reject
|
||||
? [
|
||||
{
|
||||
child: t('user.team.Reinvite'),
|
||||
label: t('user.team.Reinvite'),
|
||||
onClick: () => {
|
||||
onUpdateMember({
|
||||
teamId: item.teamId,
|
||||
@@ -379,7 +381,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
]
|
||||
: []),
|
||||
{
|
||||
child: t('user.team.Remove Member Tip'),
|
||||
label: t('user.team.Remove Member Tip'),
|
||||
onClick: () =>
|
||||
openRemoveMember(
|
||||
() =>
|
||||
|
@@ -4,13 +4,14 @@ import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
|
||||
const TeamManageModal = dynamic(() => import('../TeamManageModal'));
|
||||
|
||||
const TeamMenu = () => {
|
||||
const theme = useTheme();
|
||||
const { feConfigs } = useSystemStore();
|
||||
const { t } = useTranslation();
|
||||
const { userInfo } = useUserStore();
|
||||
const { toast } = useToast();
|
||||
|
@@ -15,15 +15,16 @@ import { getTeamList, updateInviteResult } from '@/web/support/user/team/api';
|
||||
import { TeamMemberStatusEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
const UpdateInviteModal = () => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const { toast } = useToast();
|
||||
const { ConfirmModal, openConfirm } = useConfirm({});
|
||||
const { feConfigs } = useSystemStore();
|
||||
|
||||
const { data: inviteList = [], refetch } = useQuery(['getInviteList'], () =>
|
||||
feConfigs.isPlus ? getTeamList(TeamMemberStatusEnum.waiting) : []
|
||||
|
@@ -1,29 +1,21 @@
|
||||
import React from 'react';
|
||||
import { Box, CloseButton } from '@chakra-ui/react';
|
||||
import {
|
||||
chatModelList,
|
||||
vectorModelList,
|
||||
qaModelList,
|
||||
cqModelList,
|
||||
extractModelList,
|
||||
qgModelList,
|
||||
audioSpeechModelList,
|
||||
reRankModelList,
|
||||
whisperModel
|
||||
} from '@/web/common/system/staticData';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Markdown from '@/components/Markdown';
|
||||
|
||||
const Price = ({ onClose }: { onClose: () => void }) => {
|
||||
const { llmModelList, vectorModelList, audioSpeechModelList, whisperModel } = useSystemStore();
|
||||
|
||||
const list = [
|
||||
{
|
||||
title: '对话模型',
|
||||
title: 'AI语言模型',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 输入价格(¥) | 输出价格(¥) |
|
||||
| --- | --- | --- |
|
||||
${chatModelList
|
||||
${llmModelList
|
||||
?.map((item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`)
|
||||
.join('\n')}`
|
||||
},
|
||||
@@ -36,51 +28,6 @@ ${chatModelList
|
||||
${vectorModelList?.map((item) => `| ${item.name} | ${item.inputPrice}/1k 字符 |`).join('\n')}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: '文件预处理模型(QA 拆分)',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 价格(¥) |
|
||||
| --- | --- |
|
||||
${qaModelList?.map((item) => `| ${item.name} | ${item.inputPrice}/1k 字符 |`).join('\n')}
|
||||
`
|
||||
},
|
||||
{
|
||||
title: '问题分类',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 输入价格(¥) | 输出价格(¥) |
|
||||
| --- | --- | --- |
|
||||
${cqModelList
|
||||
?.map(
|
||||
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
|
||||
)
|
||||
.join('\n')}`
|
||||
},
|
||||
{
|
||||
title: '内容提取',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 输入价格(¥) | 输出价格(¥) |
|
||||
| --- | --- | --- |
|
||||
${extractModelList
|
||||
?.map(
|
||||
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
|
||||
)
|
||||
.join('\n')}`
|
||||
},
|
||||
{
|
||||
title: '下一步指引',
|
||||
describe: '',
|
||||
md: `
|
||||
| 模型 | 输入价格(¥) | 输出价格(¥) |
|
||||
| --- | --- | --- |
|
||||
${qgModelList
|
||||
?.map(
|
||||
(item) => `| ${item.name} | ${item.inputPrice}/1k tokens | ${item.outputPrice}/1k tokens |`
|
||||
)
|
||||
.join('\n')}`
|
||||
},
|
||||
{
|
||||
title: '语音播放',
|
||||
describe: '',
|
||||
|
@@ -26,8 +26,7 @@ import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { useConfirm } from '@/web/common/hooks/useConfirm';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { useRouter } from 'next/router';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
|
||||
import MySelect from '@/components/Select';
|
||||
import {
|
||||
@@ -40,21 +39,20 @@ import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/bill/tools
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
|
||||
const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
const datasetStoreFreeSize = feConfigs?.subscription?.datasetStoreFreeSize || 0;
|
||||
const datasetStorePrice = feConfigs?.subscription?.datasetStorePrice || 0;
|
||||
const { subPlans } = useSystemStore();
|
||||
const datasetStorePrice = subPlans?.extraDatasetSize?.price || 0;
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const { ConfirmModal, openConfirm } = useConfirm({});
|
||||
const { userInfo } = useUserStore();
|
||||
const [datasetSize, setDatasetSize] = useState(0);
|
||||
const [isRenew, setIsRenew] = useState('false');
|
||||
|
||||
const { data: datasetSub } = useQuery(['getTeamDatasetValidSub'], getTeamDatasetValidSub, {
|
||||
const { data: teamSubPlan } = useQuery(['getTeamDatasetValidSub'], getTeamDatasetValidSub, {
|
||||
onSuccess(res) {
|
||||
setIsRenew(res?.sub?.status === SubStatusEnum.active ? 'true' : 'false');
|
||||
setDatasetSize((res?.sub?.nextExtraDatasetSize || 0) / 1000);
|
||||
setIsRenew(res?.extraDatasetSize?.status === SubStatusEnum.active ? 'true' : 'false');
|
||||
setDatasetSize((res?.extraDatasetSize?.nextExtraDatasetSize || 0) / 1000);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -88,7 +86,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<Box>
|
||||
<Flex>
|
||||
<Box flex={'0 0 100px'}>当前额外容量:</Box>
|
||||
<Box>{datasetSub?.sub?.currentExtraDatasetSize || 0}条</Box>
|
||||
<Box>{teamSubPlan?.extraDatasetSize?.currentExtraDatasetSize || 0}条</Box>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box flex={'0 0 100px'}>新的额外容量:</Box>
|
||||
@@ -96,7 +94,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box flex={'0 0 100px'}>新套餐价格:</Box>
|
||||
<Box>{formatStorePrice2Read(res.newPrice)}元</Box>
|
||||
<Box>{formatStorePrice2Read(res.newPlanPrice)}元</Box>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box flex={'0 0 100px'}>本次需支付:</Box>
|
||||
@@ -151,7 +149,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
</Flex>
|
||||
<Markdown
|
||||
source={`
|
||||
| 免费知识库 | ${datasetStoreFreeSize}条 |
|
||||
| 套餐知识库容量 | ${teamSubPlan?.standardMaxDatasetSize || Infinity}条 |
|
||||
| --- | --- |
|
||||
| 额外知识库 | ${datasetStorePrice}元/1000条/月 |
|
||||
`}
|
||||
@@ -160,29 +158,29 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<Flex mt={4}>
|
||||
<Box flex={'0 0 120px'}>{t('support.wallet.subscription.Current dataset store')}: </Box>
|
||||
<Box ml={2} fontWeight={'bold'} flex={1}>
|
||||
{datasetSub?.sub?.currentExtraDatasetSize || 0}
|
||||
{teamSubPlan?.extraDatasetSize?.currentExtraDatasetSize || 0}
|
||||
{t('core.dataset.data.unit')}
|
||||
</Box>
|
||||
</Flex>
|
||||
{datasetSub?.sub?.nextExtraDatasetSize !== undefined && (
|
||||
{teamSubPlan?.extraDatasetSize?.nextExtraDatasetSize !== undefined && (
|
||||
<Flex mt={4}>
|
||||
<Box flex={'0 0 120px'}>{t('support.wallet.subscription.Next sub dataset size')}: </Box>
|
||||
<Box ml={2} fontWeight={'bold'} flex={1}>
|
||||
{datasetSub?.sub?.nextExtraDatasetSize || 0}
|
||||
{teamSubPlan?.extraDatasetSize?.nextExtraDatasetSize || 0}
|
||||
{t('core.dataset.data.unit')}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!datasetSub?.sub?.startTime && (
|
||||
{!!teamSubPlan?.extraDatasetSize?.startTime && (
|
||||
<Flex mt={3}>
|
||||
<Box flex={'0 0 120px'}>订阅开始时间: </Box>
|
||||
<Box ml={2}>{formatTime2YMDHM(datasetSub?.sub?.startTime)}</Box>
|
||||
<Box ml={2}>{formatTime2YMDHM(teamSubPlan?.extraDatasetSize?.startTime)}</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!datasetSub?.sub?.expiredTime && (
|
||||
{!!teamSubPlan?.extraDatasetSize?.expiredTime && (
|
||||
<Flex mt={3}>
|
||||
<Box flex={'0 0 120px'}>订阅到期时间: </Box>
|
||||
<Box ml={2}>{formatTime2YMDHM(datasetSub?.sub?.expiredTime)}</Box>
|
||||
<Box ml={2}>{formatTime2YMDHM(teamSubPlan?.extraDatasetSize?.expiredTime)}</Box>
|
||||
</Flex>
|
||||
)}
|
||||
<Flex mt={3} alignItems={'center'}>
|
||||
@@ -205,7 +203,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<NumberInput
|
||||
flex={1}
|
||||
min={0}
|
||||
max={1000}
|
||||
max={10000}
|
||||
step={1}
|
||||
value={datasetSize}
|
||||
position={'relative'}
|
||||
@@ -213,7 +211,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
setDatasetSize(Number(e));
|
||||
}}
|
||||
>
|
||||
<NumberInputField value={datasetSize} step={1} min={0} max={1000} />
|
||||
<NumberInputField value={datasetSize} step={1} min={0} max={10000} />
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
@@ -227,7 +225,7 @@ const SubDatasetModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<Button variant={'whiteBase'} onClick={onClose}>
|
||||
{t('common.Close')}
|
||||
</Button>
|
||||
{datasetSize * 1000 !== datasetSub?.sub?.nextExtraDatasetSize && (
|
||||
{datasetSize * 1000 !== teamSubPlan?.extraDatasetSize?.nextExtraDatasetSize && (
|
||||
<Button ml={3} isLoading={isLoading} onClick={onClickPreviewCheck}>
|
||||
{t('common.Confirm')}
|
||||
</Button>
|
||||
|
Reference in New Issue
Block a user