This commit is contained in:
Archer
2023-12-27 11:07:39 +08:00
committed by GitHub
parent 86286efb54
commit 759a2330e6
182 changed files with 3099 additions and 81685 deletions

View File

@@ -18,11 +18,11 @@ const Badge = ({
{count > 0 && (
<Box position={'absolute'} right={0} top={0} transform={'translate(70%,-50%)'}>
{isDot ? (
<Box w={'5px'} h={'5px'} bg={'myRead.600'} borderRadius={'20px'}></Box>
<Box w={'5px'} h={'5px'} bg={'red.600'} borderRadius={'20px'}></Box>
) : (
<Box
color={'white'}
bg={'myRead.600'}
bg={'red.600'}
lineHeight={0.9}
borderRadius={'100px'}
px={'4px'}

View File

@@ -49,7 +49,7 @@ const FeedbackModal = ({
<Textarea ref={ref} rows={10} placeholder={t('chat.Feedback Modal Tip')} />
</ModalBody>
<ModalFooter>
<Button variant={'base'} mr={2} onClick={onClose}>
<Button variant={'whiteBase'} mr={2} onClick={onClose}>
{t('Cancel')}
</Button>
<Button isLoading={isLoading} onClick={mutate}>

View File

@@ -216,7 +216,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
pl={5}
alignItems={'center'}
bg={'white'}
color={'blue.500'}
color={'primary.500'}
visibility={isSpeaking && isTransCription ? 'visible' : 'hidden'}
>
<Spinner size={'sm'} mr={4} />
@@ -244,7 +244,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
alignItems={'center'}
justifyContent={'center'}
rounded={'md'}
color={'blue.500'}
color={'primary.500'}
top={0}
left={0}
bottom={0}
@@ -260,7 +260,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
h={'16px'}
color={'myGray.700'}
cursor={'pointer'}
_hover={{ color: 'blue.500' }}
_hover={{ color: 'primary.500' }}
position={'absolute'}
bg={'white'}
right={'-8px'}
@@ -396,7 +396,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
name={isSpeaking ? 'core/chat/stopSpeechFill' : 'core/chat/recordFill'}
width={['20px', '22px']}
height={['20px', '22px']}
color={'blue.500'}
color={'primary.500'}
/>
</MyTooltip>
</Flex>
@@ -415,7 +415,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
h={['28px', '32px']}
w={['28px', '32px']}
borderRadius={'md'}
bg={isSpeaking || isChatting ? '' : !havInput ? '#E5E5E5' : 'blue.500'}
bg={isSpeaking || isChatting ? '' : !havInput ? '#E5E5E5' : 'primary.500'}
cursor={havInput ? 'pointer' : 'not-allowed'}
lineHeight={1}
onClick={() => {

View File

@@ -125,7 +125,7 @@ export const QuoteList = React.memo(function QuoteList({
className="hover-data"
display={'none'}
alignItems={'center'}
color={'blue.500'}
color={'primary.500'}
href={`/dataset/detail?datasetId=${item.datasetId}&currentTab=dataCard&collectionId=${item.collectionId}`}
>
{t('core.dataset.Go Dataset')}
@@ -184,7 +184,7 @@ export const QuoteList = React.memo(function QuoteList({
cursor={'pointer'}
color={'myGray.600'}
_hover={{
color: 'blue.600'
color: 'primary.600'
}}
onClick={() => onclickEdit(item)}
/>

View File

@@ -147,7 +147,7 @@ const ResponseTags = ({
name="common/routePushLight"
w={'14px'}
cursor={'pointer'}
_hover={{ color: 'blue.500' }}
_hover={{ color: 'primary.500' }}
onClick={async (e) => {
e.stopPropagation();

View File

@@ -70,7 +70,7 @@ const SelectMarkCollection = ({
}}
{...(selected
? {
bg: 'blue.200'
bg: 'primary.200'
}
: {})}
onClick={() => {
@@ -132,7 +132,7 @@ const SelectMarkCollection = ({
CustomFooter={
<ModalFooter>
<Button
variant={'base'}
variant={'whiteBase'}
mr={2}
onClick={() => {
setAdminMarkData({

View File

@@ -505,7 +505,7 @@ const ChatBox = (
const colorMap = {
loading: 'myGray.700',
running: '#67c13b',
finish: 'blue.500'
finish: 'primary.500'
};
if (!isChatting) return;
const chatContent = chatHistory[chatHistory.length - 1];
@@ -673,7 +673,7 @@ const ChatBox = (
<Card
className="markdown"
{...MessageCardStyle}
bg={'blue.200'}
bg={'primary.200'}
borderRadius={'8px 0 8px 8px'}
textAlign={'left'}
>
@@ -1145,7 +1145,7 @@ function ChatAvatar({ src, type }: { src?: string; type: 'Human' | 'AI' }) {
borderRadius={'lg'}
border={theme.borders.base}
boxShadow={'0 0 5px rgba(0,0,0,0.1)'}
bg={type === 'Human' ? 'white' : 'blue.50'}
bg={type === 'Human' ? 'white' : 'primary.50'}
>
<Avatar src={src} w={'100%'} h={'100%'} />
</Box>
@@ -1226,7 +1226,7 @@ function ChatController({
<MyIcon
{...controlIconStyle}
name={'copy'}
_hover={{ color: 'blue.600' }}
_hover={{ color: 'primary.600' }}
onClick={() => copyData(chat.value)}
/>
</MyTooltip>

View File

@@ -19,7 +19,7 @@ const CommunityModal = ({ onClose }: { onClose: () => void }) => {
</ModalBody>
<ModalFooter>
<Button variant={'base'} onClick={onClose}>
<Button variant={'whiteBase'} onClick={onClose}>
</Button>
</ModalFooter>

View File

@@ -74,14 +74,14 @@ const Layout = ({ children }: { children: JSX.Element }) => {
return (
<>
<Box h={'100%'} bg={'myWhite.600'}>
<Box h={'100%'} bg={'myGray.100'}>
{isPc === true && (
<>
{pcUnShowLayoutRoute[router.pathname] ? (
<Auth>{children}</Auth>
) : (
<>
<Box h={'100%'} position={'fixed'} left={0} top={0} w={'70px'}>
<Box h={'100%'} position={'fixed'} left={0} top={0} w={'64px'}>
<Navbar unread={unread} />
</Box>
<Box h={'100%'} ml={'70px'} overflow={'overlay'}>

View File

@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
import { Box, Flex, Link } from '@chakra-ui/react';
import { Box, BoxProps, Flex, Link, LinkProps } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import { useUserStore } from '@/web/support/user/useUserStore';
import { useChatStore } from '@/web/core/chat/storeChat';
@@ -77,19 +77,16 @@ const Navbar = ({ unread }: { unread: number }) => {
[lastChatAppId, lastChatId, t]
);
const itemStyles: any = {
const itemStyles: BoxProps & LinkProps = {
my: 3,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
w: '54px',
h: '54px',
borderRadius: 'md',
_hover: {
bg: 'myWhite.600'
}
w: '48px',
h: '58px',
borderRadius: 'md'
};
return (
@@ -97,10 +94,8 @@ const Navbar = ({ unread }: { unread: number }) => {
flexDirection={'column'}
alignItems={'center'}
pt={6}
bg={'white'}
h={'100%'}
w={'100%'}
boxShadow={'2px 0px 8px 0px rgba(0,0,0,0.1)'}
userSelect={'none'}
>
{/* logo */}
@@ -113,13 +108,7 @@ const Navbar = ({ unread }: { unread: number }) => {
cursor={'pointer'}
onClick={() => router.push('/account')}
>
<Avatar
w={'36px'}
h={'36px'}
borderRadius={'50%'}
src={userInfo?.avatar}
fallbackSrc={HUMAN_ICON}
/>
<Avatar w={'36px'} h={'36px'} src={userInfo?.avatar} fallbackSrc={HUMAN_ICON} />
</Box>
{/* 导航列表 */}
<Box flex={1}>
@@ -129,13 +118,17 @@ const Navbar = ({ unread }: { unread: number }) => {
{...itemStyles}
{...(item.activeLink.includes(router.pathname)
? {
color: 'blue.600',
bg: 'white !important',
boxShadow: '1px 1px 10px rgba(0,0,0,0.2)'
color: 'primary.600',
bg: 'white',
boxShadow:
'0px 0px 1px 0px rgba(19, 51, 107, 0.08), 0px 4px 4px 0px rgba(19, 51, 107, 0.05)'
}
: {
color: 'myGray.500',
backgroundColor: 'transparent'
bg: 'transparent',
_hover: {
bg: 'rgba(255,255,255,0.9)'
}
})}
{...(item.link !== router.asPath
? {

View File

@@ -25,9 +25,15 @@ const Loading = ({
justifyContent={'center'}
flexDirection={'column'}
>
<Spinner thickness="4px" speed="0.65s" emptyColor="myGray.100" color="blue.500" size="xl" />
<Spinner
thickness="4px"
speed="0.65s"
emptyColor="myGray.100"
color="primary.500"
size="xl"
/>
{text && (
<Box mt={2} color="blue.600" fontWeight={'bold'}>
<Box mt={2} color="primary.600" fontWeight={'bold'}>
{text}
</Box>
)}

View File

@@ -23,7 +23,7 @@ function MyLink(e: any) {
<Box as={'li'} mb={1}>
<Box
as={'span'}
color={'blue.700'}
color={'primary.700'}
textDecoration={'underline'}
cursor={'pointer'}
onClick={() => {

View File

@@ -77,7 +77,7 @@ const QuestionGuide = ({ text }: { text: string }) => {
name={'core/chat/sendLight'}
w={'14px'}
cursor={'pointer'}
_hover={{ color: 'blue.500' }}
_hover={{ color: 'primary.500' }}
onClick={() => eventBus.emit(EventNameEnum.sendQuestion, { text })}
/>
</MyTooltip>

View File

@@ -123,7 +123,7 @@ const MermaidBlock = ({ code }: { code: string }) => {
position={'absolute'}
color={'myGray.600'}
_hover={{
color: 'blue.600'
color: 'primary.600'
}}
right={0}
top={0}

View File

@@ -4,7 +4,7 @@
width: 3px;
height: 14px;
transform: translate(4px, 2px) scaleY(1.3);
background-color: var(--chakra-colors-blue-700);
background-color: var(--chakra-colors-primary-700);
animation: blink 0.6s infinite;
}
@@ -17,7 +17,7 @@
width: 3px;
height: 14px;
transform: translate(4px, 2px) scaleY(1.3);
background-color: var(--chakra-colors-blue-700);
background-color: var(--chakra-colors-primary-700);
animation: blink 0.6s infinite;
}
}
@@ -129,7 +129,7 @@
.markdown dl,
.markdown table,
.markdown pre {
margin: 10px 0;
margin: 14px 0;
}
.markdown > h2:first-child,
.markdown > h1:first-child,
@@ -368,7 +368,7 @@
a {
text-decoration: underline;
color: var(--chakra-colors-blue-600);
color: var(--chakra-colors-primary-700);
}
table {

View File

@@ -1,11 +1,11 @@
import React, { useMemo } from 'react';
import ReactMarkdown from 'react-markdown';
import RemarkGfm from 'remark-gfm';
import RemarkMath from 'remark-math';
import RehypeKatex from 'rehype-katex';
import RemarkBreaks from 'remark-breaks';
import 'katex/dist/katex.min.css';
import RemarkMath from 'remark-math';
import RemarkBreaks from 'remark-breaks';
import RehypeKatex from 'rehype-katex';
import RemarkGfm from 'remark-gfm';
import styles from './index.module.scss';
import dynamic from 'next/dynamic';
@@ -74,7 +74,7 @@ function A({ children, ...props }: any) {
return (
<MyTooltip label={t('core.chat.markdown.Quick Question')}>
<Button
variant={'base'}
variant={'whitePrimary'}
size={'xs'}
borderRadius={'md'}
my={1}
@@ -96,10 +96,10 @@ function A({ children, ...props }: any) {
name={'core/chat/quoteSign'}
transform={'translateY(-2px)'}
w={'18px'}
color={'blue.500'}
color={'primary.500'}
cursor={'pointer'}
_hover={{
color: 'blue.700'
color: 'primary.700'
}}
onClick={() => getFileAndOpen(props.href)}
/>
@@ -112,17 +112,6 @@ function A({ children, ...props }: any) {
}
const Markdown = ({ source, isChatting = false }: { source: string; isChatting?: boolean }) => {
const components = useMemo(
() => ({
img: Image,
pre: 'div',
p: 'div',
code: Code,
a: A
}),
[]
);
const formatSource = source
.replace(/\\n/g, '\n&nbsp;')
.replace(/(http[s]?:\/\/[^\s。]+)([。,])/g, '$1 $2')
@@ -133,10 +122,15 @@ const Markdown = ({ source, isChatting = false }: { source: string; isChatting?:
className={`markdown ${styles.markdown}
${isChatting ? `${formatSource ? styles.waitingAnimation : styles.animation}` : ''}
`}
remarkPlugins={[RemarkGfm, RemarkMath, RemarkBreaks]}
remarkPlugins={[RemarkMath, RemarkGfm, RemarkBreaks]}
rehypePlugins={[RehypeKatex]}
// @ts-ignore
components={components}
components={{
img: Image,
pre: 'div',
p: (pProps) => <p {...pProps} dir="auto" />,
code: Code,
a: A
}}
linkTarget={'_blank'}
>
{formatSource}

View File

@@ -41,7 +41,7 @@ const MyMenu = ({ width, offset = [0, 10], Button, menuList }: Props) => {
e.stopPropagation();
item.onClick && item.onClick();
}}
color={item.isActive ? 'blue.500' : ''}
color={item.isActive ? 'primary.500' : ''}
whiteSpace={'pre-wrap'}
>
{item.child}

View File

@@ -70,7 +70,9 @@ const MyModal = ({
)}
{title}
<Box flex={1} />
{onClose && <ModalCloseButton position={'relative'} top={0} right={0} />}
{onClose && (
<ModalCloseButton position={'relative'} fontSize={'sm'} top={0} right={0} />
)}
</ModalHeader>
)}

View File

@@ -1,20 +1,29 @@
import React from 'react';
import { Box, useTheme, type BoxProps } from '@chakra-ui/react';
import { useTheme, type BoxProps } from '@chakra-ui/react';
import MyBox from '../common/MyBox';
const PageContainer = ({ children, ...props }: BoxProps & { isLoading?: boolean }) => {
const PageContainer = ({
children,
isLoading,
insertProps = {},
...props
}: BoxProps & { isLoading?: boolean; insertProps?: BoxProps }) => {
const theme = useTheme();
return (
<MyBox bg={'myGray.100'} h={'100%'} p={[0, 5]} px={[0, 6]} {...props}>
<Box
<MyBox h={'100%'} py={[0, '16px']} pr={[0, '16px']} {...props}>
<MyBox
isLoading={isLoading}
h={'100%'}
bg={'white'}
borderRadius={props?.borderRadius || [0, '2xl']}
border={['none', theme.borders.lg]}
borderColor={'borderColor.base'}
borderWidth={[0, 1]}
boxShadow={'1.5'}
overflow={'overlay'}
bg={'myGray.25'}
borderRadius={[0, '16px']}
{...insertProps}
>
{children}
</Box>
</MyBox>
</MyBox>
);
};

View File

@@ -32,7 +32,7 @@ const PromptTemplate = ({
cursor={'pointer'}
{...(item.title === selectTemplateTitle?.title
? {
bg: 'blue.50'
bg: 'primary.50'
}
: {})}
onClick={() => setSelectTemplateTitle(item)}

View File

@@ -54,7 +54,7 @@ const MySelect = (
width={width}
px={3}
rightIcon={<ChevronDownIcon />}
variant={'base'}
variant={'whitePrimary'}
textAlign={'left'}
_active={{
transform: 'none'
@@ -62,7 +62,7 @@ const MySelect = (
{...(isOpen
? {
boxShadow: '0px 0px 4px #A8DBFF',
borderColor: 'blue.500'
borderColor: 'primary.500'
}
: {})}
{...props}
@@ -93,7 +93,7 @@ const MySelect = (
{...menuItemStyles}
{...(value === item.value
? {
color: 'blue.500',
color: 'primary.500',
bg: 'myWhite.300'
}
: {})}

View File

@@ -44,9 +44,9 @@ const SideTabs = ({ list, size = 'md', activeId, onChange, ...props }: Props) =>
alignItems={'center'}
{...(activeId === item.id
? {
bg: ' blue.100 !important',
bg: ' primary.100 !important',
fontWeight: 'bold',
color: 'blue.600 ',
color: 'primary.600 ',
cursor: 'default'
}
: {

View File

@@ -69,18 +69,18 @@ const MySlider = ({
<SliderMark
value={value}
textAlign="center"
bg="blue.500"
bg="primary.500"
color="white"
px={1}
minW={'18px'}
w={'auto'}
h={'18px'}
lineHeight={'18px'}
borderRadius={'18px'}
fontSize={'xs'}
transform={'translate(-50%, -155%)'}
boxSizing={'border-box'}
fontSize={'11px'}
>
{value}
<Box transform={'scale(0.9)'}>{value}</Box>
</SliderMark>
<SliderTrack
bg={'#EAEDF3'}
@@ -95,9 +95,9 @@ const MySlider = ({
right: '-3px'
}}
>
<SliderFilledTrack bg={'blue.500'} />
<SliderFilledTrack bg={'primary.500'} />
</SliderTrack>
<SliderThumb border={'3px solid'} borderColor={'blue.500'}></SliderThumb>
<SliderThumb border={'3px solid'} borderColor={'primary.500'}></SliderThumb>
</Slider>
);
};

View File

@@ -55,10 +55,10 @@ const Tabs = ({ list, size = 'md', activeId, onChange, ...props }: Props) => {
whiteSpace={'nowrap'}
{...(activeId === item.id
? {
color: 'blue.600',
color: 'primary.600',
cursor: 'default',
fontWeight: 'bold',
borderBottomColor: 'blue.600'
borderBottomColor: 'primary.600'
}
: {
cursor: 'pointer'

View File

@@ -10,9 +10,9 @@ const Tag = ({ children, colorSchema = 'blue', ...props }: Props) => {
const theme = useMemo(() => {
const map = {
blue: {
borderColor: 'blue.500',
borderColor: 'primary.500',
bg: '#F2FBFF',
color: 'blue.600'
color: 'primary.600'
},
green: {
borderColor: '#67c13b',

View File

@@ -43,13 +43,13 @@ const MyRadio = ({
position={'relative'}
{...(value === item.value
? {
borderColor: 'blue.400',
bg: 'blue.50'
borderColor: 'primary.400',
bg: 'primary.50'
}
: {
bg: 'myWhite.300',
_hover: {
borderColor: 'blue.400'
borderColor: 'primary.400'
}
})}
_after={{
@@ -66,7 +66,7 @@ const MyRadio = ({
...(value === item.value
? {
border: '5px solid',
borderColor: 'blue.600'
borderColor: 'primary.600'
}
: {
border: '2px solid',

View File

@@ -52,7 +52,7 @@ const TagTextarea = ({ defaultValues, onUpdate, ...props }: Props) => {
bg={'myWhite.600'}
{...(focus && {
boxShadow: '0px 0px 4px #A8DBFF',
borderColor: 'blue.500'
borderColor: 'primary.500'
})}
{...props}
onClick={() => {
@@ -64,7 +64,7 @@ const TagTextarea = ({ defaultValues, onUpdate, ...props }: Props) => {
>
<Flex alignItems={'center'} gap={2} flexWrap={'wrap'}>
{tags.map((tag, i) => (
<Tag key={tag} colorScheme="blue" onClick={(e) => e.stopPropagation()}>
<Tag key={tag} colorScheme="primary" onClick={(e) => e.stopPropagation()}>
<TagLabel>{tag}</TagLabel>
<TagCloseButton
onClick={() => {

View File

@@ -66,7 +66,7 @@ const AIChatSettingsModal = ({
fontSize: ['sm', 'md']
};
const selectTemplateBtn: BoxProps = {
color: 'blue.500',
color: 'primary.500',
cursor: 'pointer'
};
@@ -229,7 +229,7 @@ const AIChatSettingsModal = ({
)}
</ModalBody>
<ModalFooter>
<Button variant={'base'} onClick={onClose}>
<Button variant={'whiteBase'} onClick={onClose}>
{t('Cancel')}
</Button>
<Button ml={4} onClick={handleSubmit(onSuccess)}>

View File

@@ -141,7 +141,7 @@ const DatasetParamsModal = ({
)}
</ModalBody>
<ModalFooter>
<Button variant={'base'} mr={3} onClick={onClose}>
<Button variant={'whiteBase'} mr={3} onClick={onClose}>
{t('common.Close')}
</Button>
<Button

View File

@@ -82,7 +82,7 @@ export const DatasetSelectModal = ({
p={3}
border={theme.borders.base}
boxShadow={'sm'}
bg={'blue.200'}
bg={'primary.200'}
>
<Flex alignItems={'center'} h={'38px'}>
<Avatar src={item.avatar} w={['24px', '28px']}></Avatar>

View File

@@ -104,9 +104,9 @@ const ChatTest = (
<MyTooltip label={'重置'}>
<IconButton
className="chat"
size={'sm'}
size={'smSquare'}
icon={<MyIcon name={'clear'} w={'14px'} />}
variant={'base'}
variant={'whiteDanger'}
borderRadius={'md'}
aria-label={'delete'}
onClick={(e) => {

View File

@@ -48,7 +48,7 @@ export type useFlowProviderStoreType = {
onDelNode: (nodeId: string) => void;
onChangeNode: (e: FlowNodeChangeProps) => void;
onCopyNode: (nodeId: string) => void;
onResetNode: (id: string, module: FlowModuleTemplateType) => void;
onResetNode: (e: { id: string; module: FlowModuleTemplateType }) => void;
onDelEdge: (e: {
moduleId: string;
sourceHandle?: string | undefined;
@@ -58,6 +58,13 @@ export type useFlowProviderStoreType = {
onConnect: ({ connect }: { connect: Connection }) => any;
initData: (modules: ModuleItemType[]) => void;
};
type requestEventType =
| 'onChangeNode'
| 'onCopyNode'
| 'onResetNode'
| 'onDelNode'
| 'onDelConnect'
| 'setNodes';
const StateContext = createContext<useFlowProviderStoreType>({
reactFlowWrapper: null,
@@ -107,7 +114,7 @@ const StateContext = createContext<useFlowProviderStoreType>({
initData: function (modules: ModuleItemType[]): void {
throw new Error('Function not implemented.');
},
onResetNode: function (id: string, module: FlowModuleTemplateType): void {
onResetNode: function (e): void {
throw new Error('Function not implemented.');
}
});
@@ -350,7 +357,7 @@ export const FlowProvider = ({
// reset a node data. delete edge and replace it
const onResetNode = useCallback(
(id: string, module: FlowModuleTemplateType) => {
({ id, module }: { id: string; module: FlowModuleTemplateType }) => {
setNodes((state) =>
state.map((node) => {
if (node.id === id) {
@@ -379,8 +386,7 @@ export const FlowProvider = ({
const initData = useCallback(
(modules: ModuleItemType[]) => {
const edges = appModule2FlowEdge({
modules,
onDelete: onDelConnect
modules
});
setEdges(edges);
@@ -388,19 +394,54 @@ export const FlowProvider = ({
onFixView();
},
[onDelConnect, setEdges, setNodes, onFixView]
[setEdges, setNodes, onFixView]
);
// use eventbus to avoid refresh ReactComponents
useEffect(() => {
const update = (e: FlowNodeChangeProps) => {
onChangeNode(e);
};
eventBus.on(EventNameEnum.updaterNode, update);
eventBus.on(
EventNameEnum.requestFlowEvent,
({ type, data }: { type: requestEventType; data: any }) => {
switch (type) {
case 'onChangeNode':
onChangeNode(data);
return;
case 'onCopyNode':
onCopyNode(data);
return;
case 'onResetNode':
onResetNode(data);
return;
case 'onDelNode':
onDelNode(data);
return;
case 'onDelConnect':
onDelConnect(data);
return;
case 'setNodes':
setNodes(data);
return;
}
}
);
return () => {
eventBus.off(EventNameEnum.updaterNode);
eventBus.off(EventNameEnum.requestFlowEvent);
};
}, [onChangeNode]);
}, []);
useEffect(() => {
eventBus.on(EventNameEnum.requestFlowStore, () => {
eventBus.emit('receiveFlowStore', {
nodes,
edges,
mode,
filterAppIds,
reactFlowWrapper
});
});
return () => {
eventBus.off(EventNameEnum.requestFlowStore);
};
}, [edges, filterAppIds, mode, nodes]);
const value = {
reactFlowWrapper,
@@ -429,5 +470,53 @@ export const FlowProvider = ({
export default React.memo(FlowProvider);
export const onChangeNode = (e: FlowNodeChangeProps) => {
eventBus.emit(EventNameEnum.updaterNode, e);
eventBus.emit(EventNameEnum.requestFlowEvent, {
type: 'onChangeNode',
data: e
});
};
export const onCopyNode = (nodeId: string) => {
eventBus.emit(EventNameEnum.requestFlowEvent, {
type: 'onCopyNode',
data: nodeId
});
};
export const onResetNode = (e: Parameters<useFlowProviderStoreType['onResetNode']>[0]) => {
eventBus.emit(EventNameEnum.requestFlowEvent, {
type: 'onResetNode',
data: e
});
};
export const onDelNode = (nodeId: string) => {
eventBus.emit(EventNameEnum.requestFlowEvent, {
type: 'onDelNode',
data: nodeId
});
};
export const onDelConnect = (e: Parameters<useFlowProviderStoreType['onDelConnect']>[0]) => {
eventBus.emit(EventNameEnum.requestFlowEvent, {
type: 'onDelConnect',
data: e
});
};
export const onSetNodes = (e: useFlowProviderStoreType['nodes']) => {
eventBus.emit(EventNameEnum.requestFlowEvent, {
type: 'setNodes',
data: e
});
};
export const getFlowStore = () =>
new Promise<{
nodes: useFlowProviderStoreType['nodes'];
edges: useFlowProviderStoreType['edges'];
mode: useFlowProviderStoreType['mode'];
filterAppIds: useFlowProviderStoreType['filterAppIds'];
reactFlowWrapper: useFlowProviderStoreType['reactFlowWrapper'];
}>((resolve) => {
eventBus.on('receiveFlowStore', (data: any) => {
resolve(data);
eventBus.off('receiveFlowStore');
});
eventBus.emit(EventNameEnum.requestFlowStore);
});

View File

@@ -3,24 +3,16 @@ 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 { useFlowProviderStore, type useFlowProviderStoreType } from './FlowProvider';
import { useFlowProviderStore } from './FlowProvider';
type Props = {
onClose: () => void;
};
const ImportSettings = ({
onClose,
setNodes,
setEdges,
initData
}: Props & {
setNodes: useFlowProviderStoreType['setNodes'];
setEdges: useFlowProviderStoreType['setEdges'];
initData: useFlowProviderStoreType['initData'];
}) => {
const ImportSettings = ({ onClose }: Props) => {
const { t } = useTranslation();
const { toast } = useToast();
const { setNodes, setEdges, initData } = useFlowProviderStore();
const [value, setValue] = useState('');
return (
@@ -41,7 +33,7 @@ const ImportSettings = ({
</ModalBody>
<ModalFooter>
<Button
variant="base"
variant="whiteBase"
onClick={() => {
if (!value) {
return onClose();
@@ -68,8 +60,4 @@ const ImportSettings = ({
);
};
export default React.memo(function (props: Props) {
const { setNodes, setEdges, initData } = useFlowProviderStore();
return <ImportSettings {...props} setNodes={setNodes} setEdges={setEdges} initData={initData} />;
});
export default React.memo(ImportSettings);

View File

@@ -7,11 +7,10 @@ import type {
import { useViewport, XYPosition } from 'reactflow';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import Avatar from '@/components/Avatar';
import { useFlowProviderStore, type useFlowProviderStoreType } from './FlowProvider';
import { getFlowStore, onSetNodes } from './FlowProvider';
import { customAlphabet } from 'nanoid';
import { appModule2FlowNode } from '@/utils/adapt';
import { useTranslation } from 'next-i18next';
import { useRouter } from 'next/router';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
import EmptyTip from '@/components/EmptyTip';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
@@ -19,7 +18,6 @@ import { getPreviewPluginModule } from '@/web/core/plugin/api';
import { useToast } from '@/web/common/hooks/useToast';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { moduleTemplatesList } from '@/web/core/modules/template/system';
import { ModuleTemplateTypeEnum } from '@fastgpt/global/core/module/constants';
export type ModuleTemplateProps = {
templates: FlowModuleTemplateType[];
@@ -32,20 +30,9 @@ type ModuleTemplateListProps = ModuleTemplateProps & {
type RenderListProps = {
templates: FlowModuleTemplateType[];
onClose: () => void;
setNodes: useFlowProviderStoreType['setNodes'];
reactFlowWrapper: useFlowProviderStoreType['reactFlowWrapper'];
};
const ModuleTemplateList = ({
templates,
isOpen,
onClose,
setNodes,
reactFlowWrapper
}: ModuleTemplateListProps & {
setNodes: useFlowProviderStoreType['setNodes'];
reactFlowWrapper: useFlowProviderStoreType['reactFlowWrapper'];
}) => {
const ModuleTemplateList = ({ templates, isOpen, onClose }: ModuleTemplateListProps) => {
const { t } = useTranslation();
return (
@@ -77,31 +64,16 @@ const ModuleTemplateList = ({
transition={'.2s ease'}
userSelect={'none'}
>
<RenderList
templates={templates}
onClose={onClose}
setNodes={setNodes}
reactFlowWrapper={reactFlowWrapper}
/>
<RenderList templates={templates} onClose={onClose} />
</Flex>
</>
);
};
export default React.memo(function (props: ModuleTemplateListProps) {
const { setNodes, reactFlowWrapper } = useFlowProviderStore();
export default React.memo(ModuleTemplateList);
return <ModuleTemplateList {...props} setNodes={setNodes} reactFlowWrapper={reactFlowWrapper} />;
});
const RenderList = React.memo(function RenderList({
templates,
onClose,
setNodes,
reactFlowWrapper
}: RenderListProps) {
const RenderList = React.memo(function RenderList({ templates, onClose }: RenderListProps) {
const { t } = useTranslation();
const router = useRouter();
const { isPc } = useSystemStore();
const { x, y, zoom } = useViewport();
const { setLoading } = useSystemStore();
@@ -119,6 +91,7 @@ const RenderList = React.memo(function RenderList({
const onAddNode = useCallback(
async ({ template, position }: { template: FlowModuleTemplateType; position: XYPosition }) => {
const { reactFlowWrapper, nodes } = await getFlowStore();
if (!reactFlowWrapper?.current) return;
const templateModule = await (async () => {
@@ -145,8 +118,8 @@ const RenderList = React.memo(function RenderList({
const mouseX = (position.x - reactFlowBounds.left - x) / zoom - 100;
const mouseY = (position.y - reactFlowBounds.top - y) / zoom;
setNodes((state) =>
state.concat(
onSetNodes(
nodes.concat(
appModule2FlowNode({
item: {
...templateModule,
@@ -157,7 +130,7 @@ const RenderList = React.memo(function RenderList({
)
);
},
[reactFlowWrapper, setLoading, setNodes, t, toast, x, y, zoom]
[setLoading, t, toast, x, y, zoom]
);
return templates.length === 0 ? (

View File

@@ -60,7 +60,7 @@ const SelectAppModal = ({
cursor={'pointer'}
{...(selectedApps.includes(app._id)
? {
bg: 'blue.100',
bg: 'primary.100',
onClick: () => {
setSelectedApps(selectedApps.filter((e) => e !== app._id));
}
@@ -83,7 +83,7 @@ const SelectAppModal = ({
))}
</ModalBody>
<ModalFooter>
<Button variant={'base'} onClick={onClose}>
<Button variant={'whiteBase'} onClick={onClose}>
{t('Cancel')}
</Button>
<Button

View File

@@ -1,19 +1,10 @@
import React from 'react';
import {
BezierEdge,
getBezierPath,
EdgeLabelRenderer,
EdgeProps,
getSmoothStepPath
} from 'reactflow';
import { BezierEdge, getBezierPath, EdgeLabelRenderer, EdgeProps } from 'reactflow';
import { onDelConnect } from '../../FlowProvider';
import { Flex } from '@chakra-ui/react';
import MyIcon from '@/components/Icon';
const ButtonEdge = (
props: EdgeProps<{
onDelete: (id: string) => void;
}>
) => {
const ButtonEdge = (props: EdgeProps) => {
const {
id,
sourceX,
@@ -22,7 +13,6 @@ const ButtonEdge = (
targetY,
sourcePosition,
targetPosition,
data,
selected,
style = {}
} = props;
@@ -67,12 +57,12 @@ const ButtonEdge = (
_hover={{
boxShadow: '0 0 6px 2px rgba(0, 0, 0, 0.08)'
}}
onClick={() => data?.onDelete(id)}
onClick={() => onDelConnect(id)}
>
<MyIcon
name="closeSolid"
w={'100%'}
color={selected ? 'blue.700' : 'myGray.500'}
color={selected ? 'primary.700' : 'myGray.500'}
></MyIcon>
</Flex>
</EdgeLabelRenderer>

View File

@@ -133,7 +133,8 @@ const TTSSelect = ({
<Image src="/icon/speaking.gif" w={'24px'} alt={''} />
<Button
ml={2}
variant={'gray'}
variant={'grayBase'}
color={'primary.600'}
isLoading={audioLoading}
leftIcon={<MyIcon name={'core/chat/stopSpeech'} w={'16px'} />}
onClick={() => {

View File

@@ -289,7 +289,7 @@ const VariableEdit = ({
</ModalBody>
<ModalFooter>
<Button variant={'base'} mr={3} onClick={onCloseEdit}>
<Button variant={'whiteBase'} mr={3} onClick={onCloseEdit}>
{t('common.Close')}
</Button>
<Button

View File

@@ -6,7 +6,7 @@ import Container from '../modules/Container';
import RenderInput from '../render/RenderInput';
import RenderOutput from '../render/RenderOutput';
const NodeAnswer = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodeAnswer = React.memo(function NodeAnswer({ data }: { data: FlowModuleItemType }) {
const { moduleId, inputs, outputs } = data;
return (
<NodeCard minW={'400px'} {...data}>
@@ -16,5 +16,7 @@ const NodeAnswer = ({ data }: NodeProps<FlowModuleItemType>) => {
</Container>
</NodeCard>
);
};
export default React.memo(NodeAnswer);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodeAnswer data={data} />;
}

View File

@@ -17,7 +17,7 @@ import SourceHandle from '../render/SourceHandle';
import MyTooltip from '@/components/MyTooltip';
import { onChangeNode } from '../../FlowProvider';
const NodeCQNode = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodeCQNode = React.memo(function NodeCQNode({ data }: { data: FlowModuleItemType }) {
const { t } = useTranslation();
const { moduleId, inputs } = data;
@@ -136,5 +136,7 @@ const NodeCQNode = ({ data }: NodeProps<FlowModuleItemType>) => {
</Container>
</NodeCard>
);
};
export default React.memo(NodeCQNode);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodeCQNode data={data} />;
}

View File

@@ -3,7 +3,10 @@ import { NodeProps } from 'reactflow';
import NodeCard from '../render/NodeCard';
import { FlowModuleItemType } from '@fastgpt/global/core/module/type.d';
const NodeAnswer = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodeAnswer = React.memo(function NodeAnswer({ data }: { data: FlowModuleItemType }) {
return <NodeCard {...data}></NodeCard>;
};
export default React.memo(NodeAnswer);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodeAnswer data={data} />;
}

View File

@@ -73,7 +73,7 @@ const ExtractFieldModal = ({
</ModalBody>
<ModalFooter>
<Button variant={'base'} mr={3} onClick={onClose}>
<Button variant={'whiteBase'} mr={3} onClick={onClose}>
{t('common.Close')}
</Button>
<Button onClick={handleSubmit(onSubmit)}>{t('common.Confirm')}</Button>

View File

@@ -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 = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodeExtract = React.memo(function NodeExtract({ data }: { data: FlowModuleItemType }) {
const { inputs, outputs, moduleId } = data;
const { t } = useTranslation();
const [editExtractFiled, setEditExtractField] = useState<ContextExtractAgentItemType>();
@@ -39,7 +39,7 @@ const NodeExtract = ({ data }: NodeProps<FlowModuleItemType>) => {
<Box pt={2}>
<Box position={'absolute'} top={0} right={0}>
<Button
variant={'base'}
variant={'whitePrimary'}
leftIcon={<AddIcon fontSize={'10px'} />}
onClick={() => setEditExtractField(defaultField)}
>
@@ -183,6 +183,8 @@ const NodeExtract = ({ data }: NodeProps<FlowModuleItemType>) => {
)}
</NodeCard>
);
};
});
export default React.memo(NodeExtract);
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodeExtract data={data} />;
}

View File

@@ -17,7 +17,7 @@ import { ModuleIOValueTypeEnum } from '@fastgpt/global/core/module/constants';
import { customAlphabet } from 'nanoid';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
const NodeHttp = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodeHttp = React.memo(function NodeHttp({ data }: { data: FlowModuleItemType }) {
const { moduleId, inputs, outputs } = data;
return (
@@ -31,5 +31,7 @@ const NodeHttp = ({ data }: NodeProps<FlowModuleItemType>) => {
</Container>
</NodeCard>
);
};
export default React.memo(NodeHttp);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodeHttp data={data} />;
}

View File

@@ -41,7 +41,11 @@ const createEditField = {
inputType: true
};
const NodePluginInput = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodePluginInput = React.memo(function NodePluginInput({
data
}: {
data: FlowModuleItemType;
}) {
const { t } = useTranslation();
const { moduleId, inputs, outputs } = data;
const [createField, setCreateField] = useState<EditNodeFieldType>();
@@ -65,7 +69,7 @@ const NodePluginInput = ({ data }: NodeProps<FlowModuleItemType>) => {
w={'14px'}
cursor={'pointer'}
mr={3}
_hover={{ color: 'blue.500' }}
_hover={{ color: 'primary.500' }}
onClick={() =>
setEditField({
inputType: item.type,
@@ -121,7 +125,7 @@ const NodePluginInput = ({ data }: NodeProps<FlowModuleItemType>) => {
))}
<Box textAlign={'right'} mt={5}>
<Button
variant={'base'}
variant={'whitePrimary'}
leftIcon={<SmallAddIcon />}
onClick={() => {
setCreateField(defaultCreateField);
@@ -253,5 +257,7 @@ const NodePluginInput = ({ data }: NodeProps<FlowModuleItemType>) => {
)}
</NodeCard>
);
};
export default React.memo(NodePluginInput);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodePluginInput data={data} />;
}

View File

@@ -42,7 +42,11 @@ const createEditField = {
inputType: false
};
const NodePluginOutput = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodePluginOutput = React.memo(function NodePluginOutput({
data
}: {
data: FlowModuleItemType;
}) {
const { t } = useTranslation();
const { moduleId, inputs, outputs } = data;
const [createField, setCreateField] = useState<EditNodeFieldType>();
@@ -84,7 +88,7 @@ const NodePluginOutput = ({ data }: NodeProps<FlowModuleItemType>) => {
w={'14px'}
cursor={'pointer'}
ml={3}
_hover={{ color: 'blue.500' }}
_hover={{ color: 'primary.500' }}
onClick={() =>
setEditField({
inputType: item.type,
@@ -121,7 +125,7 @@ const NodePluginOutput = ({ data }: NodeProps<FlowModuleItemType>) => {
))}
<Box textAlign={'left'} mt={5}>
<Button
variant={'base'}
variant={'whitePrimary'}
leftIcon={<SmallAddIcon />}
onClick={() => {
setCreateField(defaultCreateField);
@@ -233,5 +237,8 @@ const NodePluginOutput = ({ data }: NodeProps<FlowModuleItemType>) => {
)}
</NodeCard>
);
};
export default React.memo(NodePluginOutput);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodePluginOutput data={data} />;
}

View File

@@ -6,7 +6,11 @@ import Container from '../modules/Container';
import RenderOutput from '../render/RenderOutput';
const QuestionInputNode = ({ data }: NodeProps<FlowModuleItemType>) => {
const QuestionInputNode = React.memo(function QuestionInputNode({
data
}: {
data: FlowModuleItemType;
}) {
const { moduleId, outputs } = data;
return (
@@ -16,5 +20,8 @@ const QuestionInputNode = ({ data }: NodeProps<FlowModuleItemType>) => {
</Container>
</NodeCard>
);
};
export default React.memo(QuestionInputNode);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <QuestionInputNode data={data} />;
}

View File

@@ -7,7 +7,7 @@ import Container from '../modules/Container';
import RenderInput from '../render/RenderInput';
import RenderOutput from '../render/RenderOutput';
const NodeRunAPP = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodeRunAPP = React.memo(function NodeRunAPP({ data }: { data: FlowModuleItemType }) {
const { moduleId, inputs, outputs } = data;
return (
@@ -21,5 +21,7 @@ const NodeRunAPP = ({ data }: NodeProps<FlowModuleItemType>) => {
</Container>
</NodeCard>
);
};
export default React.memo(NodeRunAPP);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodeRunAPP data={data} />;
}

View File

@@ -7,7 +7,7 @@ import Container from '../modules/Container';
import RenderInput from '../render/RenderInput';
import RenderOutput from '../render/RenderOutput';
const NodeSimple = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodeSimple = React.memo(function NodeSimple({ data }: { data: FlowModuleItemType }) {
const { moduleId, inputs, outputs } = data;
return (
@@ -30,5 +30,7 @@ const NodeSimple = ({ data }: NodeProps<FlowModuleItemType>) => {
)}
</NodeCard>
);
};
export default React.memo(NodeSimple);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodeSimple data={data} />;
}

View File

@@ -30,7 +30,7 @@ import QGSwitch from '@/components/core/module/Flow/components/modules/QGSwitch'
import TTSSelect from '@/components/core/module/Flow/components/modules/TTSSelect';
import { splitGuideModule } from '@fastgpt/global/core/module/utils';
const NodeUserGuide = ({ data }: NodeProps<FlowModuleItemType>) => {
const NodeUserGuide = React.memo(function NodeUserGuide({ data }: { data: FlowModuleItemType }) {
const theme = useTheme();
return (
<>
@@ -50,9 +50,11 @@ const NodeUserGuide = ({ data }: NodeProps<FlowModuleItemType>) => {
</NodeCard>
</>
);
};
export default React.memo(NodeUserGuide);
});
export default function Node({ data }: NodeProps<FlowModuleItemType>) {
return <NodeUserGuide data={data} />;
}
export function WelcomeText({ data }: { data: FlowModuleItemType }) {
const { inputs, moduleId } = data;

View File

@@ -221,7 +221,7 @@ const FieldEditModal = ({
</ModalBody>
<ModalFooter>
<Button variant={'base'} mr={3} onClick={onClose}>
<Button variant={'whiteBase'} mr={3} onClick={onClose}>
{t('common.Close')}
</Button>
<Button

View File

@@ -8,11 +8,7 @@ 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 {
useFlowProviderStore,
onChangeNode,
type useFlowProviderStoreType
} from '../../FlowProvider';
import { onChangeNode, onCopyNode, onResetNode, onDelNode } from '../../FlowProvider';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
import { useSystemStore } from '@/web/common/system/useSystemStore';
@@ -27,13 +23,7 @@ type Props = FlowModuleItemType & {
isPreview?: boolean;
};
const NodeCard = (
props: Props & {
onCopyNode: useFlowProviderStoreType['onCopyNode'];
onResetNode: useFlowProviderStoreType['onResetNode'];
onDelNode: useFlowProviderStoreType['onDelNode'];
}
) => {
const NodeCard = (props: Props) => {
const { t } = useTranslation();
const {
children,
@@ -44,11 +34,9 @@ const NodeCard = (
moduleId,
flowType,
inputs,
isPreview,
onCopyNode,
onResetNode,
onDelNode
isPreview
} = props;
const theme = useTheme();
const { toast } = useToast();
const { setLoading } = useSystemStore();
@@ -77,7 +65,10 @@ const NodeCard = (
try {
setLoading(true);
const pluginModule = await getPreviewPluginModule(pluginId);
onResetNode(moduleId, pluginModule);
onResetNode({
id: moduleId,
module: pluginModule
});
} catch (e) {
return toast({
status: 'error',
@@ -130,20 +121,7 @@ const NodeCard = (
onClick: () => {}
}
],
[
flowType,
inputs,
moduleId,
name,
onCopyNode,
onDelNode,
onOpenModal,
onResetNode,
openConfirm,
setLoading,
t,
toast
]
[flowType, inputs, moduleId, name, onOpenModal, openConfirm, setLoading, t, toast]
);
return (
@@ -198,10 +176,4 @@ const NodeCard = (
);
};
export default React.memo(function (props: Props) {
const { onCopyNode, onResetNode, onDelNode } = useFlowProviderStore();
return (
<NodeCard {...props} onCopyNode={onCopyNode} onResetNode={onResetNode} onDelNode={onDelNode} />
);
});
export default React.memo(NodeCard);

View File

@@ -1,11 +1,7 @@
import { EditNodeFieldType, FlowNodeInputItemType } from '@fastgpt/global/core/module/node/type';
import React, { useMemo, useState } from 'react';
import { useTranslation } from 'next-i18next';
import {
onChangeNode,
useFlowProviderStore,
useFlowProviderStoreType
} from '../../../FlowProvider';
import { onChangeNode, useFlowProviderStoreType } from '../../../FlowProvider';
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { Box, Flex } from '@chakra-ui/react';
import MyTooltip from '@/components/MyTooltip';
@@ -20,16 +16,10 @@ const FieldEditModal = dynamic(() => import('../FieldEditModal'));
type Props = FlowNodeInputItemType & {
moduleId: string;
inputKey: string;
mode: useFlowProviderStoreType['mode'];
};
const InputLabel = ({
moduleId,
inputKey,
mode,
...item
}: Props & {
mode: useFlowProviderStoreType['mode'];
}) => {
const InputLabel = ({ moduleId, inputKey, mode, ...item }: Props) => {
const { t } = useTranslation();
const {
required = false,
@@ -41,6 +31,7 @@ const InputLabel = ({
showTargetInApp,
showTargetInPlugin
} = item;
const [editField, setEditField] = useState<EditNodeFieldType>();
const targetHandle = useMemo(() => {
@@ -81,7 +72,7 @@ const InputLabel = ({
w={'14px'}
cursor={'pointer'}
ml={3}
_hover={{ color: 'blue.500' }}
_hover={{ color: 'primary.500' }}
onClick={() =>
setEditField({
inputType: type,
@@ -153,8 +144,4 @@ const InputLabel = ({
);
};
export default React.memo(function (props: Props) {
const { mode } = useFlowProviderStore();
return <InputLabel {...props} mode={mode} />;
});
export default React.memo(InputLabel);

View File

@@ -1,4 +1,4 @@
import React, { useMemo } from 'react';
import React, { useEffect, useMemo, useState } from 'react';
import type { FlowNodeInputItemType } from '@fastgpt/global/core/module/node/type';
import { Box } from '@chakra-ui/react';
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/module/node/constant';
@@ -6,7 +6,7 @@ import dynamic from 'next/dynamic';
import InputLabel from './Label';
import type { RenderInputProps } from './type.d';
import { useFlowProviderStore, type useFlowProviderStoreType } from '../../../FlowProvider';
import { getFlowStore, type useFlowProviderStoreType } from '../../../FlowProvider';
const RenderList: {
types: `${FlowNodeInputTypeEnum}`[];
@@ -71,14 +71,9 @@ type Props = {
moduleId: string;
CustomComponent?: Record<string, (e: FlowNodeInputItemType) => React.ReactNode>;
};
const RenderInput = ({
flowInputList,
moduleId,
CustomComponent = {},
mode
}: Props & {
mode: useFlowProviderStoreType['mode'];
}) => {
const RenderInput = ({ flowInputList, moduleId, CustomComponent = {} }: Props) => {
const [mode, setMode] = useState<useFlowProviderStoreType['mode']>('app');
const sortInputs = useMemo(
() =>
flowInputList.sort((a, b) => {
@@ -108,6 +103,13 @@ const RenderInput = ({
[mode, sortInputs]
);
useEffect(() => {
async () => {
const { mode } = await getFlowStore();
setMode(mode);
};
}, []);
return (
<>
{filterInputs.map((input) => {
@@ -124,7 +126,9 @@ const RenderInput = ({
return (
input.type !== FlowNodeInputTypeEnum.hidden && (
<Box key={input.key} _notLast={{ mb: 7 }} position={'relative'}>
{!!input.label && <InputLabel moduleId={moduleId} inputKey={input.key} {...input} />}
{!!input.label && (
<InputLabel moduleId={moduleId} inputKey={input.key} mode={mode} {...input} />
)}
{!!RenderComponent && (
<Box mt={2} className={'nodrag'}>
{RenderComponent}
@@ -138,7 +142,4 @@ const RenderInput = ({
);
};
export default React.memo(function (props: Props) {
const { mode } = useFlowProviderStore();
return <RenderInput {...props} mode={mode} />;
});
export default React.memo(RenderInput);

View File

@@ -16,7 +16,7 @@ const AddInputParam = ({ inputs = [], item, moduleId }: RenderInputProps) => {
return (
<>
<Button
variant={'base'}
variant={'whitePrimary'}
leftIcon={<SmallAddIcon />}
onClick={() => {
setEditField(item.defaultEditField || {});

View File

@@ -26,7 +26,7 @@ const AiSettingRender = ({ inputs = [], moduleId }: RenderInputProps) => {
return (
<>
<Button
variant={'base'}
variant={'whitePrimary'}
leftIcon={<MyIcon name={'settingLight'} w={'14px'} />}
onClick={onOpenAIChatSetting}
>

View File

@@ -1,23 +1,14 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import type { RenderInputProps } from '../type';
import {
onChangeNode,
useFlowProviderStore,
type useFlowProviderStoreType
} from '../../../../FlowProvider';
import { getFlowStore, onChangeNode, useFlowProviderStoreType } from '../../../../FlowProvider';
import { Box, Button, Flex, useDisclosure, useTheme } from '@chakra-ui/react';
import { SelectAppItemType } from '@fastgpt/global/core/module/type';
import Avatar from '@/components/Avatar';
import SelectAppModal from '../../../../SelectAppModal';
const SelectAppRender = ({
item,
moduleId,
filterAppIds
}: RenderInputProps & {
filterAppIds: useFlowProviderStoreType['filterAppIds'];
}) => {
const SelectAppRender = ({ item, moduleId }: RenderInputProps) => {
const theme = useTheme();
const [filterAppIds, setFilterAppIds] = useState<useFlowProviderStoreType['filterAppIds']>([]);
const {
isOpen: isOpenSelectApp,
@@ -27,11 +18,18 @@ const SelectAppRender = ({
const value = item.value as SelectAppItemType | undefined;
useEffect(() => {
async () => {
const { filterAppIds } = await getFlowStore();
setFilterAppIds(filterAppIds);
};
}, []);
return (
<>
<Box onClick={onOpenSelectApp}>
{!value ? (
<Button variant={'base'} w={'100%'}>
<Button variant={'whitePrimary'} w={'100%'}>
</Button>
) : (
@@ -66,7 +64,4 @@ const SelectAppRender = ({
);
};
export default React.memo(function (props: RenderInputProps) {
const { filterAppIds } = useFlowProviderStore();
return <SelectAppRender {...props} filterAppIds={filterAppIds} />;
});
export default React.memo(SelectAppRender);

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useState } from 'react';
import type { RenderInputProps } from '../type';
import { onChangeNode, useFlowProviderStore } from '../../../../FlowProvider';
import { getFlowStore, onChangeNode, useFlowProviderStoreType } from '../../../../FlowProvider';
import { Button, useDisclosure } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constant';
@@ -11,7 +11,7 @@ import MyIcon from '@/components/Icon';
import DatasetParamsModal from '@/components/core/module/DatasetParamsModal';
const SelectDatasetParam = ({ inputs = [], moduleId }: RenderInputProps) => {
const { nodes } = useFlowProviderStore();
const [nodes, setNodes] = useState<useFlowProviderStoreType['nodes']>([]);
const { t } = useTranslation();
const [data, setData] = useState({
@@ -51,10 +51,17 @@ const SelectDatasetParam = ({ inputs = [], moduleId }: RenderInputProps) => {
});
}, [inputs]);
useEffect(() => {
async () => {
const { nodes } = await getFlowStore();
setNodes(nodes);
};
}, []);
return (
<>
<Button
variant={'base'}
variant={'whitePrimary'}
leftIcon={<MyIcon name={'settingLight'} w={'14px'} />}
onClick={onOpen}
>

View File

@@ -41,7 +41,7 @@ const OutputLabel = ({
w={'14px'}
cursor={'pointer'}
mr={3}
_hover={{ color: 'blue.500' }}
_hover={{ color: 'primary.500' }}
onClick={() =>
setEditField({
key: outputKey,

View File

@@ -17,7 +17,7 @@ const AddOutputParam = ({ outputs = [], item, moduleId }: RenderOutputProps) =>
return (
<Box textAlign={'right'}>
<Button
variant={'base'}
variant={'whitePrimary'}
leftIcon={<SmallAddIcon />}
onClick={() => {
setEditField(item.defaultEditField || {});

View File

@@ -28,7 +28,7 @@ const SourceHandle = ({ handleKey, valueType, ...props }: Props) => {
<Box
position={'absolute'}
top={'50%'}
right={'-16px'}
right={'-18px'}
transform={'translate(50%,-50%)'}
{...props}
>
@@ -40,8 +40,8 @@ const SourceHandle = ({ handleKey, valueType, ...props }: Props) => {
>
<Handle
style={{
width: '12px',
height: '12px',
width: '14px',
height: '14px',
...valueStyle
}}
type="source"

View File

@@ -9,10 +9,9 @@ import { ModuleIOValueTypeEnum } from '@fastgpt/global/core/module/constants';
interface Props extends BoxProps {
handleKey: string;
valueType?: `${ModuleIOValueTypeEnum}`;
onConnect?: OnConnect;
}
const TargetHandle = ({ handleKey, valueType, onConnect, ...props }: Props) => {
const TargetHandle = ({ handleKey, valueType, ...props }: Props) => {
const { t } = useTranslation();
const valType = valueType ?? ModuleIOValueTypeEnum.any;
@@ -28,7 +27,7 @@ const TargetHandle = ({ handleKey, valueType, onConnect, ...props }: Props) => {
<Box
position={'absolute'}
top={'50%'}
left={'-16px'}
left={'-18px'}
transform={'translate(50%,-50%)'}
{...props}
>
@@ -40,8 +39,8 @@ const TargetHandle = ({ handleKey, valueType, onConnect, ...props }: Props) => {
>
<Handle
style={{
width: '12px',
height: '12px',
width: '14px',
height: '14px',
...valueStyle
}}
type="target"

View File

@@ -11,7 +11,6 @@ import ModuleTemplateList, { type ModuleTemplateProps } from './ModuleTemplateLi
import { useFlowProviderStore } from './FlowProvider';
import 'reactflow/dist/style.css';
import type { ModuleItemType } from '@fastgpt/global/core/module/type.d';
const NodeSimple = dynamic(() => import('./components/nodes/NodeSimple'));
const nodeTypes: Record<`${FlowNodeTypeEnum}`, any> = {
@@ -34,106 +33,96 @@ const nodeTypes: Record<`${FlowNodeTypeEnum}`, any> = {
const edgeTypes = {
[EDGE_TYPE]: ButtonEdge
};
type Props = {
modules: ModuleItemType[];
Header: React.ReactNode;
} & ModuleTemplateProps;
const Container = React.memo(function Container(props: Props) {
const { modules = [], Header, templates } = props;
const Container = React.memo(function Container() {
const { reactFlowWrapper, nodes, onNodesChange, edges, onEdgesChange, onConnect } =
useFlowProviderStore();
return (
<ReactFlow
ref={reactFlowWrapper}
fitView
nodes={nodes}
edges={edges}
minZoom={0.1}
maxZoom={1.5}
defaultEdgeOptions={{
animated: true,
zIndex: 0
}}
elevateEdgesOnSelect
connectionLineStyle={{ strokeWidth: 2, stroke: '#5A646Es' }}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={(connect) => {
connect.sourceHandle &&
connect.targetHandle &&
onConnect({
connect
});
}}
>
<Background />
<Controls position={'bottom-right'} style={{ display: 'flex' }} showInteractive={false} />
</ReactFlow>
);
});
const Flow = ({
Header,
templates,
...data
}: ModuleTemplateProps & { Header: React.ReactNode }) => {
const {
isOpen: isOpenTemplate,
onOpen: onOpenTemplate,
onClose: onCloseTemplate
} = useDisclosure();
const { reactFlowWrapper, nodes, onNodesChange, edges, onEdgesChange, onConnect, initData } =
useFlowProviderStore();
useEffect(() => {
initData(JSON.parse(JSON.stringify(modules)));
}, [modules.length]);
return (
<>
{/* header */}
{Header}
<Box
minH={'400px'}
flex={'1 0 0'}
w={'100%'}
h={0}
position={'relative'}
onContextMenu={(e) => {
e.preventDefault();
return false;
}}
>
{/* open module template */}
<IconButton
position={'absolute'}
top={5}
left={5}
w={'38px'}
h={'38px'}
borderRadius={'50%'}
icon={<SmallCloseIcon fontSize={'26px'} />}
transform={isOpenTemplate ? '' : 'rotate(135deg)'}
transition={'0.2s ease'}
aria-label={''}
zIndex={1}
boxShadow={'2px 2px 6px #85b1ff'}
onClick={() => {
isOpenTemplate ? onCloseTemplate() : onOpenTemplate();
}}
/>
<ReactFlow
ref={reactFlowWrapper}
fitView
nodes={nodes}
edges={edges}
minZoom={0.1}
maxZoom={1.5}
defaultEdgeOptions={{
animated: true,
zIndex: 0
}}
elevateEdgesOnSelect
connectionLineStyle={{ strokeWidth: 2, stroke: '#5A646Es' }}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={(connect) => {
connect.sourceHandle &&
connect.targetHandle &&
onConnect({
connect
});
}}
>
<Background />
<Controls position={'bottom-right'} style={{ display: 'flex' }} showInteractive={false} />
</ReactFlow>
<ModuleTemplateList
templates={templates}
isOpen={isOpenTemplate}
onClose={onCloseTemplate}
/>
</Box>
</>
);
});
const Flow = (data: Props) => {
return (
<Box h={'100%'} position={'fixed'} zIndex={999} top={0} left={0} right={0} bottom={0}>
<ReactFlowProvider>
<Flex h={'100%'} flexDirection={'column'} bg={'#fff'}>
<Container {...data} />
{Header}
<Box
minH={'400px'}
flex={'1 0 0'}
w={'100%'}
h={0}
position={'relative'}
onContextMenu={(e) => {
e.preventDefault();
return false;
}}
>
{/* open module template */}
<IconButton
position={'absolute'}
top={5}
left={5}
size={'mdSquare'}
borderRadius={'50%'}
icon={<SmallCloseIcon fontSize={'26px'} />}
transform={isOpenTemplate ? '' : 'rotate(135deg)'}
transition={'0.2s ease'}
aria-label={''}
zIndex={1}
boxShadow={'2px 2px 6px #85b1ff'}
onClick={() => {
isOpenTemplate ? onCloseTemplate() : onOpenTemplate();
}}
/>
<Container {...data} />
<ModuleTemplateList
templates={templates}
isOpen={isOpenTemplate}
onClose={onCloseTemplate}
/>
</Box>
</Flex>
</ReactFlowProvider>
</Box>

View File

@@ -88,7 +88,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
href={feConfigs.openAPIDocUrl || getDocPath('/docs/development/openapi')}
target={'_blank'}
ml={1}
color={'blue.500'}
color={'primary.500'}
>
</Link>
@@ -119,7 +119,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
<Button
ml={3}
leftIcon={<AddIcon fontSize={'md'} />}
variant={'base'}
variant={'whitePrimary'}
onClick={() =>
setEditData({
...defaultEditData,
@@ -254,7 +254,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
</Flex>
</ModalBody>
<ModalFooter>
<Button variant="base" onClick={() => setApiKey('')}>
<Button variant="whiteBase" onClick={() => setApiKey('')}>
</Button>
</ModalFooter>
@@ -358,7 +358,7 @@ function EditKeyModal({
</ModalBody>
<ModalFooter>
<Button variant={'base'} mr={3} onClick={onClose}>
<Button variant={'whiteBase'} mr={3} onClick={onClose}>
{t('Cancel')}
</Button>

View File

@@ -12,7 +12,7 @@ const PermissionIconText = ({
return PermissionTypeMap[permission] ? (
<Flex alignItems={'center'} {...props}>
<MyIcon name={PermissionTypeMap[permission]?.iconLight as any} w={'14px'} />
<Box ml={'1px'}>{t(PermissionTypeMap[permission]?.label)}</Box>
<Box ml={'2px'}>{t(PermissionTypeMap[permission]?.label)}</Box>
</Flex>
) : null;
};

View File

@@ -135,7 +135,7 @@ function EditModal({
{!!defaultData.id ? (
<>
<Box flex={1} />
<Button variant={'base'} mr={3} onClick={onClose}>
<Button variant={'whiteBase'} mr={3} onClick={onClose}>
{t('common.Close')}
</Button>
<Button isLoading={updating} onClick={handleSubmit((data) => onclickUpdate(data))}>

View File

@@ -156,7 +156,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
<MyIcon
name={'common/addCircleLight'}
w={['16px', '18px']}
color={'blue.500'}
color={'primary.500'}
cursor={'pointer'}
/>
}
@@ -177,7 +177,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
gap={3}
{...(userInfo?.team?.teamId === team.teamId
? {
bg: 'blue.200'
bg: 'primary.200'
}
: {
_hover: {
@@ -198,9 +198,13 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
{team.teamName}
</Box>
{userInfo?.team?.teamId === team.teamId ? (
<MyIcon name={'common/tickFill'} w={'16px'} color={'blue.500'} />
<MyIcon name={'common/tickFill'} w={'16px'} color={'primary.500'} />
) : (
<Button size={'xs'} variant={'base'} onClick={() => onSwitchTeam(team.teamId)}>
<Button
size={'xs'}
variant={'whitePrimary'}
onClick={() => onSwitchTeam(team.teamId)}
>
{t('user.team.Check Team')}
</Button>
)}
@@ -235,7 +239,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
ml={2}
cursor={'pointer'}
_hover={{
color: 'blue.500'
color: 'primary.500'
}}
onClick={() => {
if (!userInfo?.team) return;
@@ -256,11 +260,11 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
</Box>
{userInfo.team.role === TeamMemberRoleEnum.owner && (
<Button
variant={'base'}
variant={'whitePrimary'}
size="sm"
borderRadius={'md'}
ml={3}
leftIcon={<MyIcon name={'common/inviteLight'} w={'14px'} color={'blue.500'} />}
leftIcon={<MyIcon name={'common/inviteLight'} w={'14px'} color={'primary.500'} />}
onClick={() => {
if (userInfo.team.maxSize <= members.length) {
toast({
@@ -278,12 +282,16 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
<Box flex={1} />
{userInfo.team.role !== TeamMemberRoleEnum.owner && (
<Button
variant={'base'}
variant={'whitePrimary'}
size="sm"
borderRadius={'md'}
ml={3}
leftIcon={
<MyIcon name={'support/account/loginoutLight'} w={'14px'} color={'blue.500'} />
<MyIcon
name={'support/account/loginoutLight'}
w={'14px'}
color={'primary.500'}
/>
}
onClick={() => {
openLeaveConfirm(() => onLeaveTeam(userInfo?.team?.teamId))();
@@ -335,7 +343,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
name={'edit'}
cursor={'pointer'}
w="14px"
_hover={{ color: 'blue.500' }}
_hover={{ color: 'primary.500' }}
/>
</MenuButton>
}

View File

@@ -19,7 +19,7 @@ const TeamMenu = () => {
return (
<Button
variant={'base'}
variant={'whitePrimary'}
userSelect={'none'}
w={'100%'}
display={'block'}