mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
perf: ui
This commit is contained in:
@@ -9,7 +9,7 @@ const Avatar = ({ w = '30px', ...props }: ImageProps) => {
|
||||
fallbackSrc={LOGO_ICON}
|
||||
fallbackStrategy={'onError'}
|
||||
borderRadius={'50%'}
|
||||
objectFit={'cover'}
|
||||
objectFit={'contain'}
|
||||
alt=""
|
||||
w={w}
|
||||
h={w}
|
||||
|
@@ -86,7 +86,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
||||
<Auth>{children}</Auth>
|
||||
) : (
|
||||
<Flex h={'100%'} flexDirection={'column'}>
|
||||
<Box flex={'1 0 0'} h={0} overflow={'overlay'}>
|
||||
<Box flex={'1 0 0'} h={0}>
|
||||
<Auth>{children}</Auth>
|
||||
</Box>
|
||||
<Box h={'50px'} borderTop={'1px solid rgba(0,0,0,0.1)'}>
|
||||
|
@@ -6,12 +6,11 @@ const PageContainer = ({ children, ...props }: BoxProps) => {
|
||||
return (
|
||||
<Box bg={'myGray.100'} h={'100%'} p={[0, 5]} px={[0, 6]} {...props}>
|
||||
<Box
|
||||
flex={1}
|
||||
h={'100%'}
|
||||
bg={'white'}
|
||||
borderRadius={['', '2xl']}
|
||||
border={['', theme.borders.lg]}
|
||||
overflowY={'auto'}
|
||||
borderRadius={[0, '2xl']}
|
||||
border={['none', theme.borders.lg]}
|
||||
overflow={'overlay'}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
|
@@ -27,8 +27,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
const where = {
|
||||
userId,
|
||||
time: {
|
||||
$gte: new Date(dateStart).setHours(0, 0, 0, 0),
|
||||
$lte: new Date(dateEnd).setHours(23, 59, 59, 999)
|
||||
$gte: dateStart,
|
||||
$lte: dateEnd
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -3,6 +3,7 @@ import { Box, Divider, Flex, useTheme, Button, Skeleton, useDisclosure } from '@
|
||||
import { useCopyData } from '@/utils/tools';
|
||||
import dynamic from 'next/dynamic';
|
||||
import MyIcon from '@/components/Icon';
|
||||
import { useGlobalStore } from '@/store/global';
|
||||
|
||||
const APIKeyModal = dynamic(() => import('@/components/APIKeyModal'), {
|
||||
ssr: false
|
||||
@@ -19,13 +20,15 @@ const API = ({ appId }: { appId: string }) => {
|
||||
} = useDisclosure();
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
|
||||
const { isPc } = useGlobalStore();
|
||||
|
||||
useEffect(() => {
|
||||
setBaseUrl(`${location.origin}/api/openapi`);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Flex flexDirection={'column'} pt={[0, 5]} h={'100%'}>
|
||||
<Box display={['none', 'flex']} px={5} alignItems={'center'}>
|
||||
<Flex px={5} alignItems={'center'}>
|
||||
<Box flex={1}>
|
||||
AppId:
|
||||
<Box
|
||||
@@ -38,32 +41,36 @@ const API = ({ appId }: { appId: string }) => {
|
||||
{appId}
|
||||
</Box>
|
||||
</Box>
|
||||
<Flex
|
||||
bg={'myWhite.600'}
|
||||
py={2}
|
||||
px={4}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
onClick={() => copyData(baseUrl, '已复制 API 地址')}
|
||||
>
|
||||
<Box border={theme.borders.md} px={2} borderRadius={'md'} fontSize={'sm'}>
|
||||
API服务器
|
||||
</Box>
|
||||
<Box ml={2} color={'myGray.900'} fontSize={['sm', 'md']}>
|
||||
{baseUrl}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Button
|
||||
ml={3}
|
||||
leftIcon={<MyIcon name={'apikey'} w={'16px'} color={''} />}
|
||||
variant={'base'}
|
||||
onClick={onOpenAPIModal}
|
||||
>
|
||||
API 秘钥
|
||||
</Button>
|
||||
</Box>
|
||||
{isPc && (
|
||||
<>
|
||||
<Flex
|
||||
bg={'myWhite.600'}
|
||||
py={2}
|
||||
px={4}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
onClick={() => copyData(baseUrl, '已复制 API 地址')}
|
||||
>
|
||||
<Box border={theme.borders.md} px={2} borderRadius={'md'} fontSize={'sm'}>
|
||||
API服务器
|
||||
</Box>
|
||||
<Box ml={2} color={'myGray.900'} fontSize={['sm', 'md']}>
|
||||
{baseUrl}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Button
|
||||
ml={3}
|
||||
leftIcon={<MyIcon name={'apikey'} w={'16px'} color={''} />}
|
||||
variant={'base'}
|
||||
onClick={onOpenAPIModal}
|
||||
>
|
||||
API 秘钥
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
<Divider mt={3} />
|
||||
<Box flex={1}>
|
||||
<Box flex={'1 0 0'} h={0}>
|
||||
<Skeleton h="100%" isLoaded={isLoaded} fadeDuration={2}>
|
||||
<iframe
|
||||
style={{
|
||||
|
@@ -66,7 +66,7 @@ const Settings = ({ appId }: { appId: string }) => {
|
||||
|
||||
return (
|
||||
<Flex h={'100%'} flexDirection={'column'} position={'relative'}>
|
||||
<Box w={'100%'} pt={[0, 7]} px={[2, 5, 8]}>
|
||||
<Box w={'100%'} pt={[0, 7]} px={[3, 5, 8]}>
|
||||
<Grid gridTemplateColumns={['1fr', 'repeat(2,1fr)']} gridGap={[2, 4, 6]}>
|
||||
<Box>
|
||||
<Box mb={2} fontSize={['md', 'xl']}>
|
||||
|
@@ -8,7 +8,7 @@ import React, {
|
||||
useImperativeHandle,
|
||||
ForwardedRef
|
||||
} from 'react';
|
||||
import { Box, Flex, IconButton, useOutsideClick } from '@chakra-ui/react';
|
||||
import { Box, Flex, IconButton } from '@chakra-ui/react';
|
||||
import MyIcon from '@/components/Icon';
|
||||
import { FlowModuleTypeEnum } from '@/constants/flow';
|
||||
import { streamFetch } from '@/api/fetch';
|
||||
@@ -35,7 +35,6 @@ const ChatTest = (
|
||||
},
|
||||
ref: ForwardedRef<ChatTestComponentRef>
|
||||
) => {
|
||||
const BoxRef = useRef(null);
|
||||
const ChatBoxRef = useRef<ComponentRef>(null);
|
||||
const isOpen = useMemo(() => modules && modules.length > 0, [modules]);
|
||||
|
||||
@@ -67,13 +66,6 @@ const ChatTest = (
|
||||
[app._id, app.name, modules]
|
||||
);
|
||||
|
||||
useOutsideClick({
|
||||
ref: BoxRef,
|
||||
handler: () => {
|
||||
onClose();
|
||||
}
|
||||
});
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
resetChatTest() {
|
||||
ChatBoxRef.current?.resetHistory([]);
|
||||
@@ -84,7 +76,6 @@ const ChatTest = (
|
||||
return (
|
||||
<>
|
||||
<Flex
|
||||
ref={BoxRef}
|
||||
zIndex={3}
|
||||
flexDirection={'column'}
|
||||
position={'absolute'}
|
||||
@@ -136,6 +127,7 @@ const ChatTest = (
|
||||
left={0}
|
||||
bottom={0}
|
||||
right={0}
|
||||
onClick={onClose}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
@@ -3,6 +3,7 @@ import { Box, Flex, useOutsideClick } from '@chakra-ui/react';
|
||||
import { ModuleTemplates } from '@/constants/flow/ModuleTemplate';
|
||||
import type { AppModuleTemplateItemType } from '@/types/app';
|
||||
import type { XYPosition } from 'reactflow';
|
||||
import { useGlobalStore } from '@/store/global';
|
||||
import Avatar from '@/components/Avatar';
|
||||
|
||||
const ModuleStoreList = ({
|
||||
@@ -14,15 +15,7 @@ const ModuleStoreList = ({
|
||||
onAddNode: (e: { template: AppModuleTemplateItemType; position: XYPosition }) => void;
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
const BoxRef = useRef(null);
|
||||
|
||||
useOutsideClick({
|
||||
ref: BoxRef,
|
||||
handler: () => {
|
||||
onClose();
|
||||
}
|
||||
});
|
||||
|
||||
const { isPc } = useGlobalStore();
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
@@ -33,17 +26,17 @@ const ModuleStoreList = ({
|
||||
left={0}
|
||||
bottom={0}
|
||||
w={'360px'}
|
||||
></Box>
|
||||
onClick={onClose}
|
||||
/>
|
||||
<Flex
|
||||
zIndex={3}
|
||||
ref={BoxRef}
|
||||
flexDirection={'column'}
|
||||
position={'absolute'}
|
||||
top={'65px'}
|
||||
left={0}
|
||||
pb={4}
|
||||
h={isOpen ? 'calc(100% - 100px)' : '0'}
|
||||
w={isOpen ? '360px' : '0'}
|
||||
w={isOpen ? ['100%', '360px'] : '0'}
|
||||
bg={'white'}
|
||||
boxShadow={'3px 0 20px rgba(0,0,0,0.2)'}
|
||||
borderRadius={'20px'}
|
||||
@@ -51,11 +44,11 @@ const ModuleStoreList = ({
|
||||
transition={'.2s ease'}
|
||||
userSelect={'none'}
|
||||
>
|
||||
<Box w={'330px'} py={4} px={5} fontSize={'xl'} fontWeight={'bold'}>
|
||||
<Box w={['100%', '330px']} py={4} px={5} fontSize={'xl'} fontWeight={'bold'}>
|
||||
系统模块
|
||||
</Box>
|
||||
<Box flex={'1 0 0'} overflow={'overlay'}>
|
||||
<Box w={'330px'} mx={'auto'}>
|
||||
<Box w={['100%', '330px']} mx={'auto'}>
|
||||
{ModuleTemplates.map((item) =>
|
||||
item.list.map((item) => (
|
||||
<Flex
|
||||
@@ -73,6 +66,14 @@ const ModuleStoreList = ({
|
||||
position: { x: e.clientX, y: e.clientY }
|
||||
});
|
||||
}}
|
||||
onClick={(e) => {
|
||||
if (isPc) return;
|
||||
onAddNode({
|
||||
template: item,
|
||||
position: { x: e.clientX, y: e.clientY }
|
||||
});
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<Avatar src={item.logo} w={'34px'} objectFit={'contain'} borderRadius={'0'} />
|
||||
<Box ml={5} flex={'1 0 0'}>
|
||||
|
@@ -67,7 +67,7 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<Box display={['block', 'flex']} h={'100%'}>
|
||||
<Flex flexDirection={['column', 'row']} h={'100%'}>
|
||||
{/* pc tab */}
|
||||
<Box
|
||||
display={['none', 'flex']}
|
||||
@@ -121,7 +121,7 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
</Box>
|
||||
{/* phone tab */}
|
||||
<Box display={['block', 'none']} textAlign={'center'} px={5} py={3}>
|
||||
<Box className="textlg" fontSize={'3xl'} fontWeight={'bold'}>
|
||||
<Box className="textlg" fontSize={'xl'} fontWeight={'bold'}>
|
||||
{appDetail.name}
|
||||
</Box>
|
||||
<Tabs
|
||||
@@ -140,12 +140,12 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Box flex={1} h={'100%'}>
|
||||
<Box flex={'1 0 0'} h={[0, '100%']} overflow={['overlay', '']}>
|
||||
{currentTab === TabEnum.settings && <Settings appId={appId} />}
|
||||
{currentTab === TabEnum.API && <API appId={appId} />}
|
||||
{currentTab === TabEnum.share && <Share appId={appId} />}
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
@@ -22,6 +22,7 @@ import { useToast } from '@/hooks/useToast';
|
||||
import { postCreateApp } from '@/api/app';
|
||||
import { useRouter } from 'next/router';
|
||||
import { appTemplates } from '@/constants/flow/ModuleTemplate';
|
||||
import { useGlobalStore } from '@/store/global';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
|
||||
@@ -37,6 +38,7 @@ const CreateModal = ({ onClose, onSuccess }: { onClose: () => void; onSuccess: (
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const theme = useTheme();
|
||||
const { isPc } = useGlobalStore();
|
||||
const { register, setValue, getValues, handleSubmit } = useForm<FormType>({
|
||||
defaultValues: {
|
||||
avatar: '/icon/logo.png',
|
||||
@@ -100,9 +102,9 @@ const CreateModal = ({ onClose, onSuccess }: { onClose: () => void; onSuccess: (
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal isOpen onClose={onClose}>
|
||||
<Modal isOpen onClose={onClose} isCentered={!isPc}>
|
||||
<ModalOverlay />
|
||||
<ModalContent w={'700px'} maxW={'90vw'}>
|
||||
<ModalContent maxW={'min(700px,90vw)'}>
|
||||
<ModalHeader fontSize={'2xl'}>创建属于你的 AI 应用</ModalHeader>
|
||||
<ModalBody>
|
||||
<Box color={'myGray.800'} fontWeight={'bold'}>
|
||||
@@ -121,19 +123,20 @@ const CreateModal = ({ onClose, onSuccess }: { onClose: () => void; onSuccess: (
|
||||
</MyTooltip>
|
||||
<Input
|
||||
ml={4}
|
||||
autoFocus
|
||||
bg={'myWhite.600'}
|
||||
{...register('name', {
|
||||
required: '应用名不能为空~'
|
||||
})}
|
||||
/>
|
||||
</Flex>
|
||||
<Box mt={7} mb={3} color={'myGray.800'} fontWeight={'bold'}>
|
||||
<Box mt={[4, 7]} mb={[0, 3]} color={'myGray.800'} fontWeight={'bold'}>
|
||||
从模板中选择
|
||||
</Box>
|
||||
<Grid
|
||||
userSelect={'none'}
|
||||
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)']}
|
||||
gridGap={4}
|
||||
gridGap={[2, 4]}
|
||||
>
|
||||
{appTemplates.map((item) => (
|
||||
<Card
|
||||
|
@@ -141,6 +141,14 @@ const Kb = () => {
|
||||
</Card>
|
||||
))}
|
||||
</Grid>
|
||||
{myKbList.length === 0 && (
|
||||
<Flex mt={'35vh'} flexDirection={'column'} alignItems={'center'}>
|
||||
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
|
||||
<Box mt={2} color={'myGray.500'}>
|
||||
还没有知识库,快去创建一个吧!
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
<ConfirmChild />
|
||||
</PageContainer>
|
||||
);
|
||||
|
@@ -39,8 +39,8 @@ const BillTable = () => {
|
||||
} = usePagination<UserBillType>({
|
||||
api: getUserBills,
|
||||
params: {
|
||||
dateStart: dateRange.from,
|
||||
dateEnd: dateRange.to
|
||||
dateStart: new Date(dateRange.from || new Date()).setHours(0, 0, 0, 0),
|
||||
dateEnd: new Date(dateRange.to || new Date()).setHours(23, 59, 59, 999)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -85,14 +85,14 @@ const BillTable = () => {
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
<Flex w={'100%'} mt={4} justifyContent={'flex-end'}>
|
||||
<Flex w={'100%'} mt={4} justifyContent={'flex-end'} flexWrap={'wrap'}>
|
||||
<DateRangePicker
|
||||
defaultDate={dateRange}
|
||||
position="top"
|
||||
onChange={setDateRange}
|
||||
onSuccess={() => getData(1)}
|
||||
/>
|
||||
<Box ml={2}>
|
||||
<Box ml={[0, 2]} mt={[3, 0]} w={['100%', 'auto']}>
|
||||
<Pagination />
|
||||
</Box>
|
||||
</Flex>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
import { Card, Box, Flex, Button, Input, Grid, useDisclosure } from '@chakra-ui/react';
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import { Card, Box, Flex, Button, Grid, useDisclosure } from '@chakra-ui/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { UserUpdateParams } from '@/types/user';
|
||||
import { putUserInfo, getPromotionInitData } from '@/api/user';
|
||||
@@ -14,7 +14,6 @@ import dynamic from 'next/dynamic';
|
||||
import { useSelectFile } from '@/hooks/useSelectFile';
|
||||
import { compressImg } from '@/utils/file';
|
||||
import { getErrText, useCopyData } from '@/utils/tools';
|
||||
import { authOpenAiKey } from '@/utils/plugin/openai';
|
||||
|
||||
import Loading from '@/components/Loading';
|
||||
import Avatar from '@/components/Avatar';
|
||||
|
Reference in New Issue
Block a user