chore(ui): login page & workflow page (#3046)

* login page & number input & multirow select & llm select

* workflow

* adjust nodes
This commit is contained in:
heheer
2024-11-04 10:32:38 +08:00
committed by archer
parent e1f5483432
commit 9e8138e55f
71 changed files with 745 additions and 525 deletions

View File

@@ -1,12 +1,37 @@
<svg width="1041" height="1348" viewBox="0 0 1041 1348" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M340.837 0.33933L681.068 0.338989V0.455643C684.032 0.378397 686.999 0.339702 689.967 0.339702C735.961 0.3397 781.504 9.62899 823.997 27.6772C866.49 45.7254 905.099 72.1791 937.622 105.528C970.144 138.877 995.942 178.467 1013.54 222.04C1031.14 265.612 1040.2 312.312 1040.2 359.474L340.836 359.474L340.836 1347.84C296.157 1347.84 251.914 1338.55 210.636 1320.49C169.357 1302.43 131.85 1275.95 100.257 1242.58C68.6636 1209.21 43.6023 1169.59 26.5041 1125.99C11.3834 1087.43 2.75216 1046.42 0.957956 1004.81H0.605869L0.605897 368.098H0.70363C0.105752 341.831 2.23741 315.443 7.14306 289.411C20.2709 219.745 52.6748 155.754 100.257 105.528C147.839 55.3017 208.462 21.0975 274.461 7.24017C296.426 2.62833 318.657 0.339101 340.837 0.33933Z" fill="url(#paint0_linear_1172_228)"/>
<path d="M633.639 904.645H513.029V576.37H635.422V576.377C678.161 576.607 720.454 585.093 759.951 601.37C799.997 617.874 836.384 642.064 867.033 672.559C897.683 703.054 921.996 739.257 938.583 779.101C955.171 818.944 963.709 861.648 963.709 904.775H633.639V904.645Z" fill="url(#paint1_linear_1172_228)"/>
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.5938 10.9C21.5938 9.45229 21.1475 8.03706 20.3113 6.8333C19.4751 5.62954 18.2866 4.69132 16.8961 4.13729C15.5056 3.58326 13.9755 3.4383 12.4993 3.72075C11.0231 4.00319 9.66715 4.70034 8.60288 5.72406C7.53861 6.74777 6.81384 8.05206 6.52021 9.47199C6.22658 10.8919 6.37728 12.3637 6.95326 13.7013C7.52923 15.0388 8.50462 16.182 9.75606 16.9864C11.0075 17.7907 12.4788 18.22 13.9839 18.22V10.9H21.5938Z" fill="url(#paint0_linear_0_5622)"/>
<path d="M29.6263 10.9C29.6263 9.93877 29.4498 8.98691 29.1069 8.09882C28.764 7.21072 28.2613 6.40377 27.6277 5.72405C26.9941 5.04433 26.2418 4.50515 25.414 4.13729C24.5861 3.76943 23.6987 3.58009 22.8027 3.58009C21.9066 3.58009 21.0192 3.76943 20.1913 4.13729C19.3635 4.50515 18.6112 5.04434 17.9776 5.72406C17.344 6.40378 16.8413 7.21072 16.4984 8.09882C16.1555 8.98692 15.979 9.93877 15.979 10.9L29.6263 10.9Z" fill="url(#paint1_linear_0_5622)"/>
<path d="M28.3745 22.634C28.3745 21.8174 28.2342 21.0087 27.9617 20.2543C27.6892 19.4998 27.2898 18.8143 26.7863 18.2368C26.2828 17.6594 25.685 17.2013 25.0272 16.8888C24.3693 16.5763 23.6642 16.4155 22.9521 16.4155V22.634H28.3745Z" fill="url(#paint2_linear_0_5622)"/>
<path d="M13.9836 20.3912C12.9843 20.3912 11.9947 20.5635 11.0715 20.8985C10.1482 21.2334 9.30926 21.7242 8.60262 22.3431C7.89597 22.9619 7.33543 23.6966 6.95299 24.5051C6.57056 25.3137 6.37372 26.1803 6.37372 27.0554C6.37372 27.9306 6.57056 28.7972 6.95299 29.6057C7.33543 30.4143 7.89597 31.1489 8.60262 31.7678C9.30926 32.3866 10.1482 32.8775 11.0715 33.2124C11.9947 33.5473 12.9843 33.7197 13.9836 33.7197L13.9836 20.3912Z" fill="url(#paint3_linear_0_5622)"/>
<path d="M13.9837 10.6101L13.9837 26.9823L6.3736 26.9823L6.3736 10.6101H13.9837Z" fill="url(#paint4_linear_0_5622)"/>
<path d="M23.0327 10.8988L13.8973 10.8988L13.8973 3.58008L23.0327 3.58008V10.8988Z" fill="url(#paint5_linear_0_5622)"/>
<path d="M23.0327 22.6316H17.9771V16.4155L23.0327 16.4155V22.6316Z" fill="url(#paint6_linear_0_5622)"/>
<defs>
<linearGradient id="paint0_linear_1172_228" x1="520.404" y1="0.338989" x2="520.404" y2="1347.84" gradientUnits="userSpaceOnUse">
<linearGradient id="paint0_linear_0_5622" x1="18" y1="3.58008" x2="18" y2="33.7197" gradientUnits="userSpaceOnUse">
<stop stop-color="#326DFF"/>
<stop offset="1" stop-color="#8EAEFF"/>
</linearGradient>
<linearGradient id="paint1_linear_1172_228" x1="738.369" y1="576.37" x2="738.369" y2="904.775" gradientUnits="userSpaceOnUse">
<linearGradient id="paint1_linear_0_5622" x1="18" y1="3.58008" x2="18" y2="33.7197" gradientUnits="userSpaceOnUse">
<stop stop-color="#326DFF"/>
<stop offset="1" stop-color="#8EAEFF"/>
</linearGradient>
<linearGradient id="paint2_linear_0_5622" x1="18" y1="3.58008" x2="18" y2="33.7197" gradientUnits="userSpaceOnUse">
<stop stop-color="#326DFF"/>
<stop offset="1" stop-color="#8EAEFF"/>
</linearGradient>
<linearGradient id="paint3_linear_0_5622" x1="18" y1="3.58008" x2="18" y2="33.7197" gradientUnits="userSpaceOnUse">
<stop stop-color="#326DFF"/>
<stop offset="1" stop-color="#8EAEFF"/>
</linearGradient>
<linearGradient id="paint4_linear_0_5622" x1="18" y1="3.58008" x2="18" y2="33.7197" gradientUnits="userSpaceOnUse">
<stop stop-color="#326DFF"/>
<stop offset="1" stop-color="#8EAEFF"/>
</linearGradient>
<linearGradient id="paint5_linear_0_5622" x1="18" y1="3.58008" x2="18" y2="33.7197" gradientUnits="userSpaceOnUse">
<stop stop-color="#326DFF"/>
<stop offset="1" stop-color="#8EAEFF"/>
</linearGradient>
<linearGradient id="paint6_linear_0_5622" x1="18" y1="3.58008" x2="18" y2="33.7197" gradientUnits="userSpaceOnUse">
<stop stop-color="#326DFF"/>
<stop offset="1" stop-color="#8EAEFF"/>
</linearGradient>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,4 @@
<svg width="12" height="11" viewBox="0 0 12 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.45093 7.94055L8.82385 0.567627" stroke="#8A95A7" stroke-linecap="round"/>
<path d="M4.8418 7.953L8.82373 3.97107" stroke="#8A95A7" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 271 B

View File

@@ -68,7 +68,9 @@ const SettingLLMModel = ({
<Button
w={'100%'}
justifyContent={'flex-start'}
variant={'whiteBase'}
variant={'whitePrimaryOutline'}
size={'lg'}
fontSize={'sm'}
bg={bg}
_active={{
transform: 'none'
@@ -81,8 +83,9 @@ const SettingLLMModel = ({
w={'18px'}
/>
}
rightIcon={<MyIcon name={'common/select'} w={'1rem'} />}
pl={4}
rightIcon={<MyIcon name={'common/select'} w={'1.2rem'} color={'myGray.500'} />}
px={3}
pr={2}
onClick={onOpenAIChatSetting}
>
<Box flex={1} textAlign={'left'}>

View File

@@ -59,7 +59,9 @@ const FileSelect = ({
return (
<Flex alignItems={'center'}>
<MyIcon name={'core/app/simpleMode/file'} mr={2} w={'20px'} />
<FormLabel {...labelStyle}>{t('app:file_upload')}</FormLabel>
<FormLabel color={'myGray.600'} {...labelStyle}>
{t('app:file_upload')}
</FormLabel>
<ChatFunctionTip type={'file'} />
<Box flex={1} />
<MyTooltip label={t('app:config_file_upload')}>
@@ -68,6 +70,7 @@ const FileSelect = ({
iconSpacing={1}
size={'sm'}
mr={'-5px'}
color={'myGray.600'}
onClick={onOpen}
>
{formLabel}

View File

@@ -87,7 +87,7 @@ const InputGuideConfig = ({
<Flex alignItems={'center'}>
<MyIcon name={'core/app/inputGuides'} mr={2} w={'20px'} />
<Flex alignItems={'center'}>
<FormLabel>{chatT('input_guide')}</FormLabel>
<FormLabel color={'myGray.600'}>{chatT('input_guide')}</FormLabel>
<ChatFunctionTip type={'inputGuide'} />
</Flex>
<Box flex={1} />
@@ -97,6 +97,7 @@ const InputGuideConfig = ({
iconSpacing={1}
size={'sm'}
mr={'-5px'}
color={'myGray.600'}
onClick={onOpen}
>
{formLabel}

View File

@@ -11,7 +11,7 @@ const QGSwitch = (props: SwitchProps) => {
return (
<Flex alignItems={'center'}>
<MyIcon name={'core/chat/QGFill'} mr={2} w={'20px'} />
<FormLabel>{t('common:core.app.Question Guide')}</FormLabel>
<FormLabel color={'myGray.600'}>{t('common:core.app.Question Guide')}</FormLabel>
<ChatFunctionTip type={'nextQuestion'} />
<Box flex={1} />
<Switch {...props} />

View File

@@ -270,7 +270,7 @@ const ScheduledTriggerConfig = ({
<Flex alignItems={'center'}>
<MyIcon name={'core/app/schedulePlan'} w={'20px'} />
<HStack ml={2} flex={1} spacing={1}>
<FormLabel>{t('common:core.app.Interval timer run')}</FormLabel>
<FormLabel color={'myGray.600'}>{t('common:core.app.Interval timer run')}</FormLabel>
<QuestionTip label={t('common:core.app.Interval timer tip')} />
</HStack>
<MyTooltip label={t('common:core.app.Config schedule plan')}>
@@ -279,6 +279,7 @@ const ScheduledTriggerConfig = ({
iconSpacing={1}
size={'sm'}
mr={'-5px'}
color={'myGray.600'}
onClick={onOpen}
>
{formatLabel}

View File

@@ -82,7 +82,7 @@ const TTSSelect = ({
return (
<Flex alignItems={'center'}>
<MyIcon name={'core/app/simpleMode/tts'} mr={2} w={'20px'} />
<FormLabel>{t('common:core.app.TTS')}</FormLabel>
<FormLabel color={'myGray.600'}>{t('common:core.app.TTS')}</FormLabel>
<ChatFunctionTip type={'tts'} />
<Box flex={1} />
<MyTooltip label={t('common:core.app.Select TTS')}>
@@ -92,6 +92,7 @@ const TTSSelect = ({
size={'sm'}
mr={'-5px'}
onClick={onOpen}
color={'myGray.600'}
>
{formLabel}
</Button>

View File

@@ -173,7 +173,9 @@ const VariableEdit = ({
{/* Row box */}
<Flex alignItems={'center'}>
<MyIcon name={'core/app/simpleMode/variable'} w={'20px'} />
<FormLabel ml={2}>{t('common:core.module.Variable')}</FormLabel>
<FormLabel ml={2} color={'myGray.600'}>
{t('common:core.module.Variable')}
</FormLabel>
<ChatFunctionTip type={'variable'} />
<Box flex={1} />
<Button
@@ -181,6 +183,7 @@ const VariableEdit = ({
leftIcon={<SmallAddIcon />}
iconSpacing={1}
size={'sm'}
color={'myGray.600'}
mr={'-5px'}
onClick={() => {
reset(addVariable());
@@ -193,60 +196,96 @@ const VariableEdit = ({
{formatVariables.length > 0 && (
<Box mt={2} borderRadius={'md'} overflow={'hidden'} borderWidth={'1px'} borderBottom="none">
<TableContainer>
<Table>
<Thead>
<Table bg={'white'}>
<Thead h={8}>
<Tr>
<Th
fontSize={'mini'}
borderRadius={'none !important'}
w={'18px !important'}
bg={'myGray.50'}
p={0}
/>
<Th fontSize={'mini'}>{t('workflow:Variable_name')}</Th>
<Th fontSize={'mini'}>{t('app:global_variables_desc')}</Th>
<Th fontSize={'mini'}>{t('common:common.Require Input')}</Th>
<Th fontSize={'mini'} borderRadius={'none !important'}></Th>
px={4}
fontWeight={'medium'}
>
{t('common:core.module.variable.key')}
</Th>
<Th fontSize={'mini'} bg={'myGray.50'} p={0} px={4} fontWeight={'medium'}>
{t('workflow:Variable_name')}
</Th>
<Th fontSize={'mini'} bg={'myGray.50'} p={0} px={4} fontWeight={'medium'}>
{t('common:common.Require Input')}
</Th>
<Th
fontSize={'mini'}
borderRadius={'none !important'}
bg={'myGray.50'}
p={0}
px={4}
fontWeight={'medium'}
>
{t('common:common.Operation')}
</Th>
</Tr>
</Thead>
<Tbody>
{formatVariables.map((item) => (
<Tr key={item.id}>
<Td p={0} pl={3}>
<MyIcon name={item.icon as any} w={'16px'} color={'myGray.500'} />
</Td>
<Td>{item.key}</Td>
<Td
maxW={'200px'}
fontSize={'sm'}
whiteSpace={'pre-wrap'}
wordBreak={'break-all'}
px={0}
p={0}
px={4}
h={8}
color={'myGray.900'}
fontSize={'mini'}
fontWeight={'medium'}
>
{item.description || '-'}
<Flex alignItems={'center'}>
<MyIcon name={item.icon as any} w={'16px'} color={'myGray.400'} mr={2} />
{item.label}
</Flex>
</Td>
<Td>{item.required ? '✔' : '-'}</Td>
<Td>
<MyIcon
mr={3}
name={'common/settingLight'}
w={'16px'}
cursor={'pointer'}
onClick={() => {
const formattedItem = {
...item,
list: item.enums || []
};
reset(formattedItem);
}}
/>
<MyIcon
name={'delete'}
w={'16px'}
cursor={'pointer'}
onClick={() =>
onChange(variables.filter((variable) => variable.id !== item.id))
}
/>
<Td
p={0}
px={4}
h={8}
color={'myGray.900'}
fontSize={'mini'}
fontWeight={'medium'}
>
<Flex alignItems={'center'}>{item.key}</Flex>
</Td>
<Td p={0} px={4} h={8} color={'myGray.900'} fontSize={'mini'}>
<Flex alignItems={'center'}>
{item.required ? (
<MyIcon name={'check'} w={'16px'} color={'myGray.900'} mr={2} />
) : (
''
)}
</Flex>
</Td>
<Td p={0} px={4} h={8} color={'myGray.600'} fontSize={'mini'}>
<Flex alignItems={'center'}>
<MyIcon
mr={3}
name={'common/settingLight'}
w={'16px'}
cursor={'pointer'}
onClick={() => {
const formattedItem = {
...item,
list: item.enums || []
};
reset(formattedItem);
}}
/>
<MyIcon
name={'delete'}
w={'16px'}
cursor={'pointer'}
onClick={() =>
onChange(variables.filter((variable) => variable.id !== item.id))
}
/>
</Flex>
</Td>
</Tr>
))}

View File

@@ -13,17 +13,20 @@ const WelcomeTextConfig = (props: TextareaProps) => {
<>
<Flex alignItems={'center'}>
<MyIcon name={'core/app/simpleMode/chat'} w={'20px'} />
<FormLabel ml={2}>{t('common:core.app.Welcome Text')}</FormLabel>
<FormLabel ml={2} color={'myGray.600'}>
{t('common:core.app.Welcome Text')}
</FormLabel>
<ChatFunctionTip type={'welcome'} />
</Flex>
<MyTextarea
className="nowheel"
iconSrc={'core/app/simpleMode/chat'}
title={t('common:core.app.Welcome Text')}
mt={2}
mt={1.5}
rows={6}
fontSize={'sm'}
bg={'myGray.50'}
bg={'white'}
minW={'384px'}
placeholder={t('common:core.app.tip.welcomeTextTip')}
autoHeight
minH={100}

View File

@@ -34,7 +34,7 @@ const WhisperConfig = ({
return (
<Flex alignItems={'center'}>
<MyIcon name={'core/app/simpleMode/whisper'} mr={2} w={'20px'} />
<FormLabel>{t('common:core.app.Whisper')}</FormLabel>
<FormLabel color={'myGray.600'}>{t('common:core.app.Whisper')}</FormLabel>
<Box flex={1} />
<MyTooltip label={t('common:core.app.Config whisper')}>
<Button
@@ -42,6 +42,7 @@ const WhisperConfig = ({
iconSpacing={1}
size={'sm'}
mr={'-5px'}
color={'myGray.600'}
onClick={onOpen}
>
{formLabel}

View File

@@ -39,6 +39,7 @@ import { useTranslation } from 'react-i18next';
import { Controller, useForm } from 'react-hook-form';
import MySelect from '@fastgpt/web/components/common/MySelect';
import MyTextarea from '@/components/common/Textarea/MyTextarea';
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
type props = {
value: UserChatItemValueItemType | AIChatItemValueItemType;
@@ -244,25 +245,15 @@ const RenderUserFormInteractive = React.memo(function RenderFormInput({
/>
)}
{input.type === FlowNodeInputTypeEnum.numberInput && (
<NumberInput
step={1}
<MyNumberInput
min={input.min}
max={input.max}
isDisabled={interactive.params.submitted}
bg={'white'}
rounded={'md'}
>
<NumberInputField
bg={'white'}
{...register(input.label, {
required: input.required
})}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
register={register}
name={input.label}
isRequired={input.required}
/>
)}
{input.type === FlowNodeInputTypeEnum.select && (
<Controller

View File

@@ -61,6 +61,7 @@ const DefaultPermissionList = ({
}
}}
fontSize={styles?.fontSize}
fontWeight={styles?.fontWeight}
/>
</Box>
<ConfirmModal />

View File

@@ -145,7 +145,6 @@ const Header = () => {
)}
<Flex
mt={[2, 0]}
py={3}
pl={[2, 4]}
pr={[2, 6]}
borderBottom={'base'}
@@ -163,12 +162,20 @@ const Header = () => {
})}
>
{/* back */}
<MyIcon
name={'common/leftArrowLight'}
w={'1.75rem'}
cursor={'pointer'}
onClick={isPublished ? onBack : onOpenBackConfirm}
/>
<Box
_hover={{
bg: 'myGray.200'
}}
p={0.5}
borderRadius={'sm'}
>
<MyIcon
name={'common/leftArrowLight'}
w={6}
cursor={'pointer'}
onClick={isPublished ? onBack : onOpenBackConfirm}
/>
</Box>
{/* app info */}
<Box ml={1}>

View File

@@ -51,6 +51,7 @@ const RouteTab = () => {
px={2}
py={0.5}
fontWeight={'medium'}
borderRadius={'sm'}
{...(currentTab === tab.id
? {
color: 'primary.700'
@@ -59,8 +60,7 @@ const RouteTab = () => {
color: 'myGray.600',
cursor: 'pointer',
_hover: {
bg: 'myGray.200',
borderRadius: 'md'
bg: 'myGray.200'
},
onClick: () => setCurrentTab(tab.id)
})}

View File

@@ -84,7 +84,7 @@ const AppCard = () => {
>
{appDetail.intro || t('common:core.app.tip.Add a intro to app')}
</Box>
<HStack alignItems={'flex-end'}>
<HStack alignItems={'center'}>
<Button
size={['sm', 'md']}
variant={'whitePrimary'}
@@ -107,7 +107,7 @@ const AppCard = () => {
<MyMenu
Button={
<IconButton
variant={'whiteBase'}
variant={'whitePrimary'}
size={['smSquare', 'mdSquare']}
icon={<MyIcon name={'more'} w={'1rem'} />}
aria-label={''}

View File

@@ -151,7 +151,6 @@ const Header = () => {
)}
<Flex
mt={[2, 0]}
py={3}
pl={[2, 4]}
pr={[2, 6]}
borderBottom={'base'}
@@ -169,12 +168,20 @@ const Header = () => {
})}
>
{/* back */}
<MyIcon
name={'common/leftArrowLight'}
w={'1.75rem'}
cursor={'pointer'}
onClick={isPublished ? onBack : onOpenBackConfirm}
/>
<Box
_hover={{
bg: 'myGray.200'
}}
p={0.5}
borderRadius={'sm'}
>
<MyIcon
name={'common/leftArrowLight'}
w={6}
cursor={'pointer'}
onClick={isPublished ? onBack : onOpenBackConfirm}
/>
</Box>
{/* app info */}
<Box ml={1}>

View File

@@ -16,6 +16,7 @@ import { publishStatusStyle } from '../constants';
import MyPopover from '@fastgpt/web/components/common/MyPopover';
import { fileDownload } from '@/web/common/file/utils';
import { AppChatConfigType } from '@fastgpt/global/core/app/type';
import MyBox from '@fastgpt/web/components/common/MyBox';
const ImportSettings = dynamic(() => import('./Flow/ImportSettings'));
@@ -27,97 +28,120 @@ const AppCard = ({
isPublished: boolean;
}) => {
const { t } = useTranslation();
const { feConfigs } = useSystemStore();
const { appDetail, onOpenInfoEdit, onOpenTeamTagModal, onDelApp, currentTab } =
useContextSelector(AppContext, (v) => v);
const { showHistoryModal } = useContextSelector(WorkflowContext, (v) => v);
const { appDetail, onOpenInfoEdit, onOpenTeamTagModal, onDelApp } = useContextSelector(
AppContext,
(v) => v
);
const { isOpen: isOpenImport, onOpen: onOpenImport, onClose: onCloseImport } = useDisclosure();
const InfoMenu = useCallback(
({ children }: { children: React.ReactNode }) => {
return (
<MyMenu
width={150}
Button={children}
menuList={[
{
children: [
{
icon: 'edit',
label: t('app:edit_info'),
onClick: onOpenInfoEdit
},
{
icon: 'support/team/key',
label: t('common:common.Role'),
onClick: onOpenInfoEdit
}
]
},
...(!showHistoryModal && currentTab === TabEnum.appEdit
? [
{
children: [
{
label: t('app:import_configs'),
icon: 'common/importLight',
onClick: onOpenImport
},
{
label: ExportPopover({
chatConfig: appDetail.chatConfig,
appName: appDetail.name
}),
menuItemStyles: {
p: 0,
cursor: 'default'
}
}
]
}
]
: []),
...(appDetail.permission.hasWritePer && feConfigs?.show_team_chat
? [
{
children: [
{
icon: 'support/team/memberLight',
label: t('common:common.Team Tags Set'),
onClick: onOpenTeamTagModal
}
]
}
]
: []),
...(appDetail.permission.isOwner
? [
{
children: [
{
type: 'danger' as 'danger',
icon: 'delete',
label: t('common:common.Delete'),
onClick: onDelApp
}
]
}
]
: [])
]}
/>
<MyPopover
placement={'bottom-end'}
hasArrow={false}
offset={[2, 4]}
w={'116px'}
trigger={'hover'}
Trigger={children}
>
{({ onClose }) => (
<Box p={1.5}>
<MyBox
display={'flex'}
size={'md'}
px={1}
py={1.5}
rounded={'4px'}
_hover={{ color: 'primary.600', bg: 'rgba(17, 24, 36, 0.05)' }}
cursor={'pointer'}
onClick={onOpenInfoEdit}
>
<MyIcon name={'edit'} w={'16px'} mr={2} />
<Box fontSize={'sm'}>{t('app:edit_info')}</Box>
</MyBox>
<MyBox
display={'flex'}
size={'md'}
px={1}
py={1.5}
rounded={'4px'}
_hover={{ color: 'primary.600', bg: 'rgba(17, 24, 36, 0.05)' }}
cursor={'pointer'}
onClick={onOpenInfoEdit}
>
<MyIcon name={'support/team/key'} w={'16px'} mr={2} />
<Box fontSize={'sm'}>{t('app:Role_setting')}</Box>
</MyBox>
<Box w={'full'} h={'1px'} bg={'myGray.200'} my={1} />
<MyBox
display={'flex'}
size={'md'}
px={1}
py={1.5}
rounded={'4px'}
_hover={{ color: 'primary.600', bg: 'rgba(17, 24, 36, 0.05)' }}
cursor={'pointer'}
onClick={onOpenImport}
>
<MyIcon name={'common/importLight'} w={'16px'} mr={2} />
<Box fontSize={'sm'}>{t('app:import_configs')}</Box>
</MyBox>
<MyBox
display={'flex'}
size={'md'}
px={1}
py={1.5}
rounded={'4px'}
_hover={{ color: 'primary.600', bg: 'rgba(17, 24, 36, 0.05)' }}
cursor={'pointer'}
>
{ExportPopover({
chatConfig: appDetail.chatConfig,
appName: appDetail.name
})}
</MyBox>
<Box w={'full'} h={'1px'} bg={'myGray.200'} my={1} />
<MyBox
display={'flex'}
size={'md'}
px={1}
py={1.5}
rounded={'4px'}
_hover={{ color: 'primary.600', bg: 'rgba(17, 24, 36, 0.05)' }}
cursor={'pointer'}
onClick={onOpenTeamTagModal}
>
<MyIcon name={'core/dataset/tag'} w={'16px'} mr={2} />
<Box fontSize={'sm'}>{t('app:Team_Tags')}</Box>
</MyBox>
<Box w={'full'} h={'1px'} bg={'myGray.200'} my={1} />
<MyBox
display={'flex'}
size={'md'}
px={1}
py={1.5}
rounded={'4px'}
color={'red.600'}
_hover={{ bg: 'rgba(17, 24, 36, 0.05)' }}
cursor={'pointer'}
onClick={onDelApp}
>
<MyIcon name={'delete'} w={'16px'} mr={2} />
<Box fontSize={'sm'}>{t('common:common.Delete')}</Box>
</MyBox>
</Box>
)}
</MyPopover>
);
},
[
appDetail.chatConfig,
appDetail.name,
appDetail.permission.hasWritePer,
appDetail.permission.isOwner,
currentTab,
feConfigs?.show_team_chat,
showHistoryModal,
onDelApp,
onOpenImport,
onOpenInfoEdit,
@@ -129,21 +153,26 @@ const AppCard = ({
const Render = useMemo(() => {
return (
<HStack>
<InfoMenu>
<Avatar src={appDetail.avatar} w={'1.75rem'} borderRadius={'md'} />
</InfoMenu>
<Avatar src={appDetail.avatar} w={'1.75rem'} borderRadius={'md'} />
<Box>
<InfoMenu>
<HStack spacing={1} cursor={'pointer'}>
<HStack
spacing={1}
cursor={'pointer'}
pl={1}
ml={-1}
borderRadius={'xs'}
_hover={{ bg: 'myGray.150' }}
>
<Box color={'myGray.900'}>{appDetail.name}</Box>
<MyIcon name={'common/select'} w={'1rem'} />
<MyIcon name={'common/select'} w={'1rem'} color={'myGray.500'} />
</HStack>
</InfoMenu>
{showSaveStatus && (
<Flex alignItems={'center'} h={'20px'} fontSize={'mini'} lineHeight={1}>
<Flex alignItems={'center'} fontSize={'mini'} lineHeight={1}>
<MyTag
py={0}
px={0}
px={1}
showDot
bg={'transparent'}
colorSchema={
@@ -211,15 +240,19 @@ function ExportPopover({
return (
<MyPopover
placement={'right-start'}
offset={[0, 0]}
offset={[0, 20]}
hasArrow
trigger={'hover'}
w={'8.6rem'}
Trigger={
<Flex align={'center'} w={'100%'} py={2} px={3}>
<Avatar src={'export'} borderRadius={'sm'} w={'1rem'} mr={3} />
{t('app:export_configs')}
</Flex>
// <Flex align={'center'} w={'100%'} py={2} px={3}>
// <Avatar src={'export'} borderRadius={'sm'} w={'1rem'} mr={3} />
// {t('app:export_configs')}
// </Flex>
<MyBox display={'flex'} size={'md'} rounded={'4px'} cursor={'pointer'}>
<MyIcon name={'export'} w={'16px'} mr={2} />
<Box fontSize={'sm'}>{t('app:export_configs')}</Box>
</MyBox>
}
>
{({ onClose }) => (

View File

@@ -116,13 +116,13 @@ const ButtonEdge = (props: EdgeProps) => {
(edge) => edge.sourceHandle === sourceHandleId && edge.targetHandle === targetHandleId
);
if (!targetEdge) {
if (highlightEdge) return '#3370ff';
if (highlightEdge) return '#487FFF';
return '#94B5FF';
}
// debug mode
const colorMap = {
[RuntimeEdgeStatusEnum.active]: '#39CC83',
[RuntimeEdgeStatusEnum.active]: '#487FFF',
[RuntimeEdgeStatusEnum.waiting]: '#5E8FFF',
[RuntimeEdgeStatusEnum.skipped]: '#8A95A7'
};

View File

@@ -6,10 +6,8 @@ const Container = ({ children, ...props }: BoxProps) => {
return (
<Flex
flexDirection={'column'}
px={4}
mx={2}
mb={2}
py={'10px'}
mx={4}
p={4}
position={'relative'}
bg={'myGray.50'}
border={'1px solid #F0F1F6'}

View File

@@ -4,7 +4,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
const IOTitle = ({ text, ...props }: { text?: 'Input' | 'Output' | string } & StackProps) => {
return (
<HStack fontSize={'md'} alignItems={'center'} fontWeight={'medium'} mb={3} {...props}>
<HStack fontSize={'md'} alignItems={'center'} fontWeight={'medium'} mb={4} {...props}>
<Box w={'3px'} h={'14px'} borderRadius={'13px'} bg={'primary.600'} />
<Box color={'myGray.900'}>{text}</Box>
</HStack>

View File

@@ -290,7 +290,7 @@ export const useWorkflow = () => {
// Loop node size and position
const resetParentNodeSizeAndPosition = useMemoizedFn((rect: Rect, parentId: string) => {
const width = rect.width + 110 > 900 ? rect.width + 110 : 900;
const height = rect.height + 380 > 900 ? rect.height + 380 : 900;
const height = rect.height + 420 > 900 ? rect.height + 420 : 900;
// Update parentNode size and position
onChangeNode({

View File

@@ -80,7 +80,7 @@ const NodeLoopEnd = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
debug: true
}}
>
<Box px={4} pb={4}>
<Box px={4} pb={4} pt={2}>
{inputItem && <Reference item={inputItem} nodeId={nodeId} />}
</Box>
</NodeCard>

View File

@@ -100,7 +100,7 @@ const NodeLoopStart = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
debug: true
}}
>
<Box px={4} w={'420px'} h={'116px'}>
<Box px={4} pt={2} w={'420px'} h={'116px'}>
{!loopItemInputType ? (
<EmptyTip text={t('workflow:loop_start_tip')} py={0} mt={4} iconSize={'32px'} />
) : (

View File

@@ -99,7 +99,7 @@ const NodeCQNode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
nodeId={nodeId}
handleId={getHandleId(nodeId, 'source', item.key)}
position={Position.Right}
translate={[26, 0]}
translate={[36, 0]}
/>
</Box>
</Box>

View File

@@ -60,7 +60,8 @@ const NodeExtract = ({ data }: NodeProps<FlowNodeItemType>) => {
</Box>
<Button
size={'sm'}
variant={'whitePrimary'}
variant={'ghost'}
color={'myGray.600'}
leftIcon={<AddIcon fontSize={'10px'} />}
onClick={() => setEditExtractField(defaultField)}
>
@@ -78,12 +79,10 @@ const NodeExtract = ({ data }: NodeProps<FlowNodeItemType>) => {
<Table bg={'white'}>
<Thead>
<Tr>
<Th bg={'myGray.50'} borderRadius={'none !important'}>
{t('common:item_name')}
</Th>
<Th bg={'myGray.50'}>{t('common:item_description')}</Th>
<Th bg={'myGray.50'}>{t('common:required')}</Th>
<Th bg={'myGray.50'} borderRadius={'none !important'}></Th>
<Th borderRadius={'none !important'}>{t('common:item_name')}</Th>
<Th>{t('common:item_description')}</Th>
<Th>{t('common:required')}</Th>
<Th borderRadius={'none !important'}></Th>
</Tr>
</Thead>
<Tbody>

View File

@@ -24,7 +24,6 @@ import {
FlowValueTypeMap
} from '@fastgpt/global/core/workflow/node/constant';
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
import MySelect from '@fastgpt/web/components/common/MySelect';
import MultipleSelect from '@fastgpt/web/components/common/MySelect/MultipleSelect';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
@@ -35,6 +34,7 @@ import { useTranslation } from 'react-i18next';
import MyIcon from '@fastgpt/web/components/common/Icon';
import DndDrag, { Draggable } from '@fastgpt/web/components/common/DndDrag';
import MyTextarea from '@/components/common/Textarea/MyTextarea';
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
type ListValueType = { id: string; value: string; label: string }[];
@@ -249,8 +249,6 @@ const InputTypeConfig = ({
{t('common:core.module.Max Length')}
</FormLabel>
<MyNumberInput
flex={'1 0 0'}
bg={'myGray.50'}
placeholder={t('common:core.module.Max Length placeholder')}
value={maxLength}
max={50000}
@@ -269,8 +267,6 @@ const InputTypeConfig = ({
{t('common:core.module.Max Value')}
</FormLabel>
<MyNumberInput
flex={'1 0 0'}
bg={'myGray.50'}
value={max}
onChange={(e) => {
// @ts-ignore
@@ -283,8 +279,6 @@ const InputTypeConfig = ({
{t('common:core.module.Min Value')}
</FormLabel>
<MyNumberInput
flex={'1 0 0'}
bg={'myGray.50'}
value={min}
onChange={(e) => {
// @ts-ignore

View File

@@ -35,6 +35,7 @@ const FieldEditModal = dynamic(() => import('./InputEditModal'));
const NodePluginInput = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
const { t } = useTranslation();
const { nodeId, inputs = [], outputs } = data;
console.log(outputs);
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
@@ -141,7 +142,7 @@ const NodePluginInput = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
}}
/>
</Container>
{!!outputs.length && (
{!!outputs.filter((output) => output.type !== FlowNodeOutputTypeEnum.hidden).length && (
<Container>
<IOTitle text={t('common:common.Output')} />
<RenderOutput nodeId={nodeId} flowOutputList={outputs} />

View File

@@ -15,7 +15,7 @@ import { WorkflowContext } from '../../context';
const NodeSimple = ({
data,
selected,
minW = '350px',
minW = '524px',
maxW
}: NodeProps<FlowNodeItemType> & { minW?: string | number; maxW?: string | number }) => {
const { t } = useTranslation();

View File

@@ -21,6 +21,7 @@ import WelcomeTextConfig from '@/components/core/app/WelcomeTextConfig';
import FileSelect from '@/components/core/app/FileSelect';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { userFilesInput } from '@fastgpt/global/core/workflow/template/system/workflowStart';
import Container from '../components/Container';
type ComponentProps = {
chatConfig: AppChatConfigType;
@@ -49,7 +50,7 @@ const NodeUserGuide = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
return (
<>
<NodeCard
minW={'300px'}
minW={'420px'}
selected={selected}
menuForbid={{
debug: true,
@@ -58,30 +59,30 @@ const NodeUserGuide = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
}}
{...data}
>
<Box px={4} py={'10px'} position={'relative'} borderRadius={'md'} className="nodrag">
<Container>
<WelcomeText {...componentsProps} />
<Box pt={4}>
<Box mt={2} pt={2}>
<ChatStartVariable {...componentsProps} />
</Box>
<Box mt={3} pt={3} borderTop={'base'}>
<Box mt={3} pt={3} borderTop={'base'} borderColor={'myGray.200'}>
<FileSelectConfig {...componentsProps} />
</Box>
<Box mt={3} pt={3} borderTop={'base'}>
<Box mt={3} pt={3} borderTop={'base'} borderColor={'myGray.200'}>
<TTSGuide {...componentsProps} />
</Box>
<Box mt={3} pt={3} borderTop={'base'}>
<Box mt={3} pt={3} borderTop={'base'} borderColor={'myGray.200'}>
<WhisperGuide {...componentsProps} />
</Box>
<Box mt={3} pt={3} borderTop={'base'}>
<Box mt={3} pt={4} borderTop={'base'} borderColor={'myGray.200'}>
<QuestionGuide {...componentsProps} />
</Box>
<Box mt={3} pt={3} borderTop={'base'}>
<Box mt={4} pt={3} borderTop={'base'} borderColor={'myGray.200'}>
<ScheduledTrigger {...componentsProps} />
</Box>
<Box mt={3} pt={3} borderTop={'base'}>
<Box mt={3} pt={3} borderTop={'base'} borderColor={'myGray.200'}>
<QuestionInputGuide {...componentsProps} />
</Box>
</Box>
</Container>
</NodeCard>
</>
);

View File

@@ -26,7 +26,7 @@ const NodeTools = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
<RenderOutput nodeId={nodeId} flowOutputList={outputs} />
</Container>
<Box position={'relative'}>
<Box borderBottomLeftRadius={'md'} borderBottomRadius={'md'} overflow={'hidden'}>
<Box mb={-4} borderBottomLeftRadius={'md'} borderBottomRadius={'md'} overflow={'hidden'}>
<Divider
showBorderBottom={false}
icon={<MyIcon name="phoneTabbar/tool" w={'16px'} h={'16px'} />}

View File

@@ -65,7 +65,7 @@ const NodeStart = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
return (
<NodeCard
minW={'240px'}
minW={'420px'}
selected={selected}
menuForbid={{
copy: true,

View File

@@ -5,6 +5,7 @@ import { handleHighLightStyle, sourceCommonStyle, handleConnectedStyle, handleSi
import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { useContextSelector } from 'use-context-selector';
import { WorkflowContext } from '../../../../context';
import MyIcon from '@fastgpt/web/components/common/Icon';
type Props = {
nodeId: string;
@@ -108,9 +109,7 @@ const MySourceHandle = React.memo(function MySourceHandle({
position={position}
isConnectableEnd={false}
>
{showAddIcon && (
<SmallAddIcon pointerEvents={'none'} color={'primary.600'} fontWeight={'bold'} />
)}
{showAddIcon && <MyIcon name={'edgeAdd'} />}
</Handle>
);
}, [handleId, position, showAddIcon, styles, transform]);

View File

@@ -1,4 +1,4 @@
export const primaryColor = '#3370FF';
export const primaryColor = '#487FFF';
export const lowPrimaryColor = '#94B5FF';
export const handleSize = {
width: '18px',

View File

@@ -25,7 +25,6 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useWorkflowUtils } from '../../hooks/useUtils';
import { WholeResponseContent } from '@/components/core/chat/components/WholeResponseModal';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { getDocPath } from '@/web/common/system/doc';
type Props = FlowNodeItemType & {
@@ -149,15 +148,17 @@ const NodeCard = (props: Props) => {
<Box position={'relative'}>
{/* debug */}
{showHeader && (
<Box px={4} py={3}>
<Box px={4} pt={4}>
{/* tool target handle */}
<ToolTargetHandle show={showToolHandle} nodeId={nodeId} />
{/* avatar and name */}
<Flex alignItems={'center'}>
{node?.flowNodeType !== FlowNodeTypeEnum.stopTool && (
<Box
mr={2}
<Flex
alignItems={'center'}
mr={1}
p={1}
cursor={'pointer'}
rounded={'sm'}
_hover={{ bg: 'myGray.200' }}
@@ -172,20 +173,20 @@ const NodeCard = (props: Props) => {
>
<MyIcon
name={!isFolded ? 'core/chat/chevronDown' : 'core/chat/chevronRight'}
w={'24px'}
h={'24px'}
w={'16px'}
h={'16px'}
color={'myGray.500'}
/>
</Box>
</Flex>
)}
<Avatar
src={avatar}
borderRadius={'sm'}
objectFit={'contain'}
w={'30px'}
h={'30px'}
w={'24px'}
h={'24px'}
/>
<Box ml={3} fontSize={'md'} fontWeight={'medium'}>
<Box ml={2} fontSize={'18px'} fontWeight={'medium'} color={'myGray.900'}>
{t(name as any)}
</Box>
<MyIcon
@@ -330,13 +331,16 @@ const NodeCard = (props: Props) => {
maxW={maxW}
minH={minH}
bg={'white'}
borderWidth={'1px'}
borderRadius={'md'}
boxShadow={'1'}
outline={selected ? '2px solid' : '1px solid'}
borderRadius={'lg'}
boxShadow={
'0px 4px 10px 0px rgba(19, 51, 107, 0.10), 0px 0px 1px 0px rgba(19, 51, 107, 0.10)'
}
w={w}
h={h}
_hover={{
boxShadow: '4',
boxShadow:
'0px 12px 16px -4px rgba(19, 51, 107, 0.20), 0px 0px 1px 0px rgba(19, 51, 107, 0.20)',
'& .controller-menu': {
display: 'flex'
},
@@ -351,17 +355,19 @@ const NodeCard = (props: Props) => {
onMouseLeave={() => setHoverNodeId(undefined)}
{...(isError
? {
borderColor: 'red.500',
outlineColor: 'red.500',
onMouseDownCapture: () => onUpdateNodeError(nodeId, false)
}
: {
borderColor: selected ? 'primary.600' : 'borderColor.base'
outlineColor: selected ? 'primary.600' : 'myGray.250'
})}
{...customStyle}
>
<NodeDebugResponse nodeId={nodeId} debugResult={debugResult} />
{Header}
{!isFolded && children}
<Flex flexDirection={'column'} flex={1} my={4} gap={2}>
{!isFolded ? children : <Box h={4} />}
</Flex>
{RenderHandle}
{RenderToolHandle}
@@ -568,31 +574,35 @@ const NodeIntro = React.memo(function NodeIntro({
const Render = useMemo(() => {
return (
<>
<Flex alignItems={'flex-end'} py={1}>
<Box fontSize={'xs'} color={'myGray.600'} flex={'1 0 0'}>
<Flex alignItems={'center'}>
<Box fontSize={'sm'} color={'myGray.500'} flex={'1 0 0'}>
{t(intro as any)}
</Box>
{NodeIsTool && (
<Button
size={'xs'}
variant={'whiteBase'}
onClick={() => {
onOpenIntroModal({
defaultVal: intro,
onSuccess(e) {
onChangeNode({
nodeId,
type: 'attr',
key: 'intro',
value: e
});
}
});
}}
>
{t('common:core.module.Edit intro')}
</Button>
)}
<Flex
p={'7px'}
rounded={'sm'}
alignItems={'center'}
_hover={{
bg: NodeIsTool ? 'myGray.100' : 'transparent'
}}
cursor={NodeIsTool ? 'pointer' : 'default'}
onClick={() => {
if (!NodeIsTool) return;
onOpenIntroModal({
defaultVal: intro,
onSuccess(e) {
onChangeNode({
nodeId,
type: 'attr',
key: 'intro',
value: e
});
}
});
}}
>
<MyIcon name={'edit'} w={'18px'} opacity={NodeIsTool ? 1 : 0} />
</Flex>
</Flex>
<EditIntroModal maxLength={500} />
</>

View File

@@ -9,6 +9,7 @@ import {
} from '@chakra-ui/react';
import { useContextSelector } from 'use-context-selector';
import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context';
import MyIcon from '@fastgpt/web/components/common/Icon';
const NumberInputRender = ({ item, nodeId }: RenderInputProps) => {
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
@@ -19,6 +20,8 @@ const NumberInputRender = ({ item, nodeId }: RenderInputProps) => {
defaultValue={item.value}
min={item.min}
max={item.max}
bg={'white'}
rounded={'md'}
onChange={(e) => {
onChangeNode({
nodeId,
@@ -31,10 +34,31 @@ const NumberInputRender = ({ item, nodeId }: RenderInputProps) => {
});
}}
>
<NumberInputField bg={'white'} px={3} borderRadius={'sm'} />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
<NumberInputField
bg={'white'}
px={3}
rounded={'md'}
_hover={{
borderColor: 'primary.500'
}}
/>
<NumberInputStepper roundedTopRight={'none'}>
<NumberIncrementStepper
borderTopRightRadius={'sm !important'}
_hover={{
bg: 'myGray.100'
}}
>
<MyIcon name={'core/chat/chevronUp'} width={'12px'} />
</NumberIncrementStepper>
<NumberDecrementStepper
borderBottomRightRadius={'sm !important'}
_hover={{
bg: 'myGray.100'
}}
>
<MyIcon name={'core/chat/chevronDown'} width={'12px'} />
</NumberDecrementStepper>
</NumberInputStepper>
</NumberInput>
);

View File

@@ -130,7 +130,7 @@ export const useReference = ({
label: (
<Flex alignItems={'center'}>
<Avatar src={node.avatar} w={'1.25rem'} borderRadius={'xs'} />
<Box ml={1}>{t(node.name as any)}</Box>
<Box ml={2}>{t(node.name as any)}</Box>
</Flex>
),
value: node.nodeId,
@@ -205,7 +205,7 @@ export const ReferSelector = ({
selectItemLabel ? (
<Flex alignItems={'center'}>
{selectItemLabel[0].label}
<MyIcon name={'common/rightArrowLight'} mx={1} w={'14px'}></MyIcon>
<MyIcon name={'core/chat/chevronRight'} mx={1} w={4} />
{selectItemLabel[1].label}
</Flex>
) : (

View File

@@ -302,9 +302,9 @@ const SettingQuotePrompt = (props: RenderInputProps) => {
return (
<>
<Flex className="nodrag" cursor={'default'} alignItems={'center'} position={'relative'}>
<Box position={'relative'} color={'myGray.600'} fontWeight={'medium'}>
<FormLabel position={'relative'} color={'myGray.600'} fontWeight={'medium'}>
{t('common:core.module.Dataset quote.label')}
</Box>
</FormLabel>
<ValueTypeLabel
valueType={WorkflowIOValueTypeEnum.datasetQuote}
valueDesc={datasetQuoteValueDesc}
@@ -320,7 +320,7 @@ const SettingQuotePrompt = (props: RenderInputProps) => {
/>
</MyTooltip>
</Flex>
<Box mt={1}>
<Box mt={3}>
<Reference {...props} />
</Box>

View File

@@ -139,7 +139,7 @@ const RenderOutput = ({
<FormLabel
key={output.key}
required={output.required}
mb={i === renderOutputs.length - 1 ? 0 : 5}
mb={i === renderOutputs.length - 1 ? 0 : 4}
position={'relative'}
>
<OutputLabel nodeId={nodeId} output={output} />

View File

@@ -1,12 +1,7 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import React, { useCallback, useMemo, useRef } from 'react';
import {
Box,
Flex,
NumberInput,
NumberInputField,
NumberInputStepper,
NumberIncrementStepper,
NumberDecrementStepper,
Input,
Button,
ModalBody,
@@ -29,6 +24,8 @@ import { useContextSelector } from 'use-context-selector';
import { DatasetImportContext } from '../Context';
import { useToast } from '@fastgpt/web/hooks/useToast';
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
function DataProcess({ showPreviewChunks = true }: { showPreviewChunks: boolean }) {
const { t } = useTranslation();
@@ -127,14 +124,7 @@ function DataProcess({ showPreviewChunks = true }: { showPreviewChunks: boolean
<Box>
<Flex alignItems={'center'}>
<Box>{t('dataset:ideal_chunk_length')}</Box>
<MyTooltip label={t('dataset:ideal_chunk_length_tips')}>
<MyIcon
name={'common/questionLight'}
ml={1}
w={'14px'}
color={'myGray.500'}
/>
</MyTooltip>
<QuestionTip label={t('dataset:ideal_chunk_length_tips')} />
</Flex>
<Box
mt={1}
@@ -150,30 +140,18 @@ function DataProcess({ showPreviewChunks = true }: { showPreviewChunks: boolean
max: maxChunkSize
})}
>
<NumberInput
size={'sm'}
step={100}
<MyNumberInput
name={chunkSizeField}
min={minChunkSize}
max={maxChunkSize}
size={'sm'}
step={100}
value={chunkSize}
onChange={(e) => {
if (e === undefined) return;
setValue(chunkSizeField, +e);
}}
>
<NumberInputField
min={minChunkSize}
max={maxChunkSize}
{...register(chunkSizeField, {
min: minChunkSize,
max: maxChunkSize,
valueAsNumber: true
})}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
/>
</MyTooltip>
</Box>
</Box>
@@ -182,14 +160,9 @@ function DataProcess({ showPreviewChunks = true }: { showPreviewChunks: boolean
<Box mt={3}>
<Box>
{t('common:core.dataset.import.Custom split char')}
<MyTooltip label={t('common:core.dataset.import.Custom split char Tips')}>
<MyIcon
name={'common/questionLight'}
ml={1}
w={'14px'}
color={'myGray.500'}
/>
</MyTooltip>
<QuestionTip
label={t('common:core.dataset.import.Custom split char Tips')}
/>
</Box>
<Box mt={1}>
<Input

View File

@@ -1,5 +1,5 @@
import React, { useState, Dispatch, useCallback } from 'react';
import { FormControl, Box, Input, Button, useDisclosure } from '@chakra-ui/react';
import React, { Dispatch } from 'react';
import { FormControl, Box, Input, Button } from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { LoginPageTypeEnum } from '@/web/support/user/login/constants';
import { postFindPassword } from '@/web/support/user/api';
@@ -73,11 +73,11 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
return (
<>
<Box fontWeight={'bold'} fontSize={'2xl'} textAlign={'center'}>
<Box fontWeight={'medium'} fontSize={'lg'} textAlign={'center'} color={'myGray.900'}>
{t('user:password.retrieved_account', { account: feConfigs?.systemTitle })}
</Box>
<Box
mt={'42px'}
mt={9}
onKeyDown={(e) => {
if (e.keyCode === 13 && !e.shiftKey && !requesting) {
handleSubmit(onclickFindPassword)();
@@ -87,6 +87,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
<FormControl isInvalid={!!errors.username}>
<Input
bg={'myGray.50'}
size={'lg'}
placeholder={placeholder}
{...register('username', {
required: t('user:password.email_phone_void'),
@@ -107,6 +108,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
>
<Input
bg={'myGray.50'}
size={'lg'}
flex={1}
maxLength={8}
placeholder={t('user:password.verification_code')}
@@ -120,6 +122,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
<Input
bg={'myGray.50'}
type={'password'}
size={'lg'}
placeholder={t('user:password.new_password')}
{...register('password', {
required: t('user:password.password_required'),
@@ -138,6 +141,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
<Input
bg={'myGray.50'}
type={'password'}
size={'lg'}
placeholder={t('user:password.confirm')}
{...register('password2', {
validate: (val) =>
@@ -148,9 +152,12 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
<Button
type="submit"
mt={10}
mt={12}
w={'100%'}
size={['md', 'md']}
rounded={['md', 'md']}
h={[10, 10]}
fontWeight={['medium', 'medium']}
colorScheme="blue"
isLoading={requesting}
onClick={handleSubmit(onclickFindPassword)}
@@ -159,9 +166,10 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
</Button>
<Box
float={'right'}
fontSize="sm"
mt={2}
fontSize="mini"
mt={3}
mb={'50px'}
fontWeight={'medium'}
color={'primary.700'}
cursor={'pointer'}
_hover={{ textDecoration: 'underline' }}

View File

@@ -80,7 +80,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
return (
<FormLayout setPageType={setPageType} pageType={LoginPageTypeEnum.passwordLogin}>
<Box
mt={'42px'}
mt={9}
onKeyDown={(e) => {
if (e.key === 'Enter' && !e.shiftKey && !requesting) {
handleSubmit(onclickLogin)();
@@ -90,15 +90,17 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
<FormControl isInvalid={!!errors.username}>
<Input
bg={'myGray.50'}
size={'lg'}
placeholder={placeholder}
{...register('username', {
required: true
})}
></Input>
</FormControl>
<FormControl mt={6} isInvalid={!!errors.password}>
<FormControl mt={7} isInvalid={!!errors.password}>
<Input
bg={'myGray.50'}
size={'lg'}
type={'password'}
placeholder={
isCommunityVersion
@@ -115,13 +117,19 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
></Input>
</FormControl>
{feConfigs?.docUrl && (
<Flex alignItems={'center'} mt={7} fontSize={'mini'}>
<Flex
alignItems={'center'}
mt={7}
fontSize={'mini'}
color={'myGray.700'}
fontWeight={'medium'}
>
{t('login:policy_tip')}
<Link
ml={1}
href={getDocPath('/docs/agreement/terms/')}
target={'_blank'}
color={'primary.500'}
color={'primary.700'}
>
{t('login:terms')}
</Link>
@@ -129,7 +137,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
<Link
href={getDocPath('/docs/agreement/privacy/')}
target={'_blank'}
color={'primary.500'}
color={'primary.700'}
>
{t('login:privacy')}
</Link>
@@ -138,9 +146,11 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
<Button
type="submit"
my={6}
my={5}
w={'100%'}
size={['md', 'md']}
h={[10, 10]}
fontWeight={['medium', 'medium']}
colorScheme="blue"
isLoading={requesting}
onClick={handleSubmit(onclickLogin)}
@@ -148,29 +158,34 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
{t('login:Login')}
</Button>
<Flex align={'center'} justifyContent={'flex-end'} color={'primary.700'}>
<Flex
align={'center'}
justifyContent={'flex-end'}
color={'primary.700'}
fontWeight={'medium'}
>
{feConfigs?.find_password_method && feConfigs.find_password_method.length > 0 && (
<Box
cursor={'pointer'}
_hover={{ textDecoration: 'underline' }}
onClick={() => setPageType('forgetPassword')}
fontSize="sm"
fontSize="mini"
>
{t('login:forget_password')}
</Box>
)}
{feConfigs?.register_method && feConfigs.register_method.length > 0 && (
<>
<Box mx={3} h={'16px'} w={'1.5px'} bg={'myGray.250'}></Box>
<Flex alignItems={'center'}>
<Box mx={3} h={'12px'} w={'1px'} bg={'myGray.250'}></Box>
<Box
cursor={'pointer'}
_hover={{ textDecoration: 'underline' }}
onClick={() => setPageType('register')}
fontSize="sm"
fontSize="mini"
>
{t('login:register')}
</Box>
</>
</Flex>
)}
</Flex>
</Box>

View File

@@ -5,7 +5,6 @@ import { Box, Center, Image } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query';
import { getWXLoginQR, getWXLoginResult } from '@/web/support/user/api';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { useRouter } from 'next/router';
import { useToast } from '@fastgpt/web/hooks/useToast';
import FormLayout from './components/FormLayout';
import { useTranslation } from 'next-i18next';
@@ -40,7 +39,7 @@ const WechatForm = ({ setPageType, loginSuccess }: Props) => {
return (
<FormLayout setPageType={setPageType} pageType={LoginPageTypeEnum.wechat}>
<Box>
<Box w={'full'} textAlign={'center'} pt={5}>
<Box w={'full'} textAlign={'center'} pt={6} fontWeight={'medium'}>
{t('common:support.user.login.wx_qr_login')}
</Box>
<Box p={5} display={'flex'} w={'full'} justifyContent={'center'}>

View File

@@ -8,7 +8,6 @@ import { customAlphabet } from 'nanoid';
import { useRouter } from 'next/router';
import { Dispatch, useRef } from 'react';
import { useTranslation } from 'next-i18next';
import Divider from '@/pages/app/detail/components/WorkflowComponents/Flow/components/Divider';
import I18nLngSelector from '@/components/Select/I18nLngSelector';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 8);
@@ -64,7 +63,7 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
{
label: t('common:support.user.login.Password login'),
provider: LoginPageTypeEnum.passwordLogin,
icon: 'support/account/passwordLogin',
icon: 'support/permission/privateLight',
pageType: LoginPageTypeEnum.passwordLogin
}
]
@@ -77,20 +76,20 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
return (
<Flex flexDirection={'column'} h={'100%'}>
<Flex alignItems={'center'} justify={'space-between'}>
<Flex>
<Flex alignItems={'center'}>
<Flex
w={['48px', '56px']}
h={['48px', '56px']}
w={['42px', '56px']}
h={['42px', '56px']}
bg={'myGray.25'}
borderRadius={'xl'}
borderWidth={'1.5px'}
borderColor={'borderColor.base'}
borderRadius={['semilg', 'lg']}
borderWidth={['1px', '1.5px']}
borderColor={'myGray.200'}
alignItems={'center'}
justifyContent={'center'}
>
<Image src={LOGO_ICON} w={['24px', '28px']} alt={'icon'} />
<Image src={LOGO_ICON} w={['22.5px', '36px']} alt={'icon'} />
</Flex>
<Box ml={3} fontSize={['2xl', '3xl']} fontWeight={'bold'}>
<Box ml={[3, 5]} fontSize={['lg', 'xl']} fontWeight={'bold'} color={'myGray.900'}>
{feConfigs?.systemTitle}
</Box>
</Flex>
@@ -101,26 +100,21 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
<>
<Box flex={1} />
<Box position={'relative'}>
<Divider />
<AbsoluteCenter bg="white" px="4" color={'myGray.500'}>
<Box h={'1px'} bg={'myGray.250'} />
<AbsoluteCenter bg={'white'} px={3} color={'myGray.500'} fontSize={'mini'}>
or
</AbsoluteCenter>
</Box>
<Box mt={8}>
<Box mt={4}>
{oAuthList.map((item) => (
<Box key={item.provider} _notFirst={{ mt: 4 }}>
<Button
variant={'whitePrimary'}
w={'100%'}
h={'42px'}
leftIcon={
<MyIcon
name={item.icon as any}
w={'20px'}
cursor={'pointer'}
color={'myGray.800'}
/>
}
h={'40px'}
borderRadius={'sm'}
fontWeight={'medium'}
leftIcon={<MyIcon name={item.icon as any} w={'20px'} />}
onClick={() => {
item.redirectUrl &&
setLoginStore({
@@ -142,7 +136,8 @@ const FormLayout = ({ children, setPageType, pageType }: Props) => {
<Button
variant={'whitePrimary'}
w={'100%'}
h={'42px'}
h={'40px'}
borderRadius={'sm'}
leftIcon={<Image alt="" src={feConfigs.sso.icon as any} w="20px" />}
onClick={() => {
feConfigs.sso?.url && router.replace(feConfigs.sso?.url, '_self');

View File

@@ -102,11 +102,11 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
return (
<>
<Box fontWeight={'bold'} fontSize={'2xl'} textAlign={'center'}>
<Box fontWeight={'medium'} fontSize={'lg'} textAlign={'center'} color={'myGray.900'}>
{t('user:register.register_account', { account: feConfigs?.systemTitle })}
</Box>
<Box
mt={'42px'}
mt={9}
onKeyDown={(e) => {
if (e.key === 'Enter' && !e.shiftKey && !requesting) {
handleSubmit(onclickRegister)();
@@ -116,6 +116,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
<FormControl isInvalid={!!errors.username}>
<Input
bg={'myGray.50'}
size={'lg'}
placeholder={placeholder}
{...register('username', {
required: t('user:password.email_phone_void'),
@@ -135,6 +136,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
position={'relative'}
>
<Input
size={'lg'}
bg={'myGray.50'}
flex={1}
maxLength={8}
@@ -148,6 +150,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
<FormControl mt={6} isInvalid={!!errors.password}>
<Input
bg={'myGray.50'}
size={'lg'}
type={'password'}
placeholder={t('user:password.new_password')}
{...register('password', {
@@ -166,6 +169,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
<FormControl mt={6} isInvalid={!!errors.password2}>
<Input
bg={'myGray.50'}
size={'lg'}
type={'password'}
placeholder={t('user:password.confirm')}
{...register('password2', {
@@ -176,9 +180,12 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
</FormControl>
<Button
type="submit"
mt={6}
mt={12}
w={'100%'}
size={['md', 'md']}
rounded={['md', 'md']}
h={[10, 10]}
fontWeight={['medium', 'medium']}
colorScheme="blue"
isLoading={requesting}
onClick={handleSubmit(onclickRegister)}
@@ -187,9 +194,10 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
</Button>
<Box
float={'right'}
fontSize="sm"
mt={2}
fontSize="mini"
mt={3}
mb={'50px'}
fontWeight={'medium'}
color={'primary.700'}
cursor={'pointer'}
_hover={{ textDecoration: 'underline' }}

View File

@@ -145,7 +145,6 @@ const Login = ({ ChineseRedirectUrl }: { ChineseRedirectUrl: string }) => {
backgroundSize={'cover'}
userSelect={'none'}
h={'100%'}
px={[0, '10vw']}
>
{isPc && (
<Box position={'absolute'} top={'24px'} right={'50px'}>
@@ -154,16 +153,15 @@ const Login = ({ ChineseRedirectUrl }: { ChineseRedirectUrl: string }) => {
)}
<Flex
flexDirection={'column'}
w={['100%', 'auto']}
h={['100%', '700px']}
maxH={['100%', '90vh']}
w={['100%', '556px']}
h={['100%', '677px']}
bg={'white'}
px={['5vw', '88px']}
py={'5vh'}
borderRadius={[0, '24px']}
py={['5vh', '64px']}
borderRadius={[0, '16px']}
boxShadow={[
'',
'0px 0px 1px 0px rgba(19, 51, 107, 0.20), 0px 32px 64px -12px rgba(19, 51, 107, 0.20)'
'0px 32px 64px -12px rgba(19, 51, 107, 0.20), 0px 0px 1px 0px rgba(19, 51, 107, 0.20)'
]}
>
<Box w={['100%', '380px']} flex={'1 0 0'}>
@@ -179,6 +177,8 @@ const Login = ({ ChineseRedirectUrl }: { ChineseRedirectUrl: string }) => {
<Box
mt={8}
color={'primary.700'}
fontSize={'mini'}
fontWeight={'medium'}
cursor={'pointer'}
textAlign={'center'}
onClick={onOpen}

View File

@@ -1,14 +1,4 @@
import {
Box,
Flex,
Grid,
NumberDecrementStepper,
NumberInput,
NumberIncrementStepper,
NumberInputField,
NumberInputStepper,
Button
} from '@chakra-ui/react';
import { Box, Flex, Grid, Button } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import React, { useCallback, useState } from 'react';
import { useSystemStore } from '@/web/common/system/useSystemStore';
@@ -19,6 +9,7 @@ import { getErrText } from '@fastgpt/global/common/error/utils';
import { getWxPayQRCode } from '@/web/support/wallet/bill/api';
import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants';
import QRCodePayModal, { type QRPayProps } from '@/components/support/wallet/QRCodePayModal';
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
const ExtraPlan = () => {
const { t } = useTranslation();
@@ -170,22 +161,14 @@ const ExtraPlan = () => {
{t('common:support.wallet.subscription.Month amount')}
</Box>
<Flex alignItems={'center'} mt={1} w={'180px'} position={'relative'}>
<NumberInput size={'sm'} flex={1} step={1} min={1} max={12} position={'relative'}>
<NumberInputField
pr={'30px'}
{...registerDatasetSize('month', {
required: true,
min: 1,
max: 12,
valueAsNumber: true
})}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Box position={'absolute'} right={'20px'} color={'myGray.600'} fontSize={'xs'}>
<MyNumberInput
name="month"
register={registerDatasetSize}
min={1}
max={12}
size={'sm'}
/>
<Box position={'absolute'} right={'30px'} color={'myGray.600'} fontSize={'xs'}>
{t('common:common.month')}
</Box>
</Flex>
@@ -195,30 +178,14 @@ const ExtraPlan = () => {
{t('common:support.wallet.subscription.Update extra dataset size')}
</Box>
<Flex alignItems={'center'} mt={1} w={'180px'} position={'relative'}>
<NumberInput
size={'sm'}
flex={1}
<MyNumberInput
name="datasetSize"
register={registerDatasetSize}
min={0}
max={10000}
step={1}
position={'relative'}
>
<NumberInputField
pr={'30px'}
{...registerDatasetSize('datasetSize', {
required: true,
min: 0,
max: 10000,
valueAsNumber: true
})}
step={1}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Box position={'absolute'} right={'20px'} color={'myGray.600'} fontSize={'xs'}>
size={'sm'}
/>
<Box position={'absolute'} right={'30px'} color={'myGray.600'} fontSize={'xs'}>
000{t('common:core.dataset.data.unit')}
</Box>
</Flex>
@@ -291,30 +258,14 @@ const ExtraPlan = () => {
position={'relative'}
color={'myGray.500'}
>
<NumberInput
size={'sm'}
flex={1}
<MyNumberInput
name="points"
register={registerDatasetSize}
min={0}
max={10000}
step={1}
position={'relative'}
>
<NumberInputField
pr={'30px'}
step={1}
{...registerExtraPoints('points', {
required: true,
min: 0,
max: 10000,
valueAsNumber: true
})}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Box position={'absolute'} right={'20px'} color={'myGray.500'} fontSize={'xs'}>
size={'sm'}
/>
<Box position={'absolute'} right={'30px'} color={'myGray.500'} fontSize={'xs'}>
{'000' + t('common:support.wallet.subscription.point')}
</Box>
</Flex>

View File

@@ -64,7 +64,8 @@ export const useSendCode = ({ type }: { type: `${UserAuthTypeEnum}` }) => {
position={'absolute'}
right={3}
zIndex={1}
fontSize={'sm'}
fontSize={'mini'}
fontWeight={'medium'}
{...styles}
{...(codeCountDown > 0
? {