From 52a752dab51263a36e4bbd30434ff2f42893c080 Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Sun, 5 Mar 2023 21:16:19 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=87=92=E5=8A=A0=E8=BD=BD=E5=92=8C?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=8A=A0=E8=BD=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icon/menu-left.svg | 1 - src/components/Layout/auth.tsx | 2 +- src/components/Layout/index.tsx | 6 +- src/hooks/useLoading.tsx | 4 +- src/hooks/useScreen.ts | 2 +- src/pages/_app.tsx | 2 +- src/pages/chat/index.tsx | 66 +++--- src/pages/index.tsx | 7 +- src/pages/login/index.tsx | 39 ++-- src/pages/model/components/CreateModel.tsx | 4 +- src/pages/model/components/ModelEditForm.tsx | 24 ++- src/pages/model/components/Training.tsx | 6 +- src/pages/model/detail.tsx | 216 ++++++++++--------- src/pages/model/list.tsx | 15 +- 14 files changed, 203 insertions(+), 191 deletions(-) delete mode 100644 public/icon/menu-left.svg diff --git a/public/icon/menu-left.svg b/public/icon/menu-left.svg deleted file mode 100644 index 7ed50b75d..000000000 --- a/public/icon/menu-left.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/Layout/auth.tsx b/src/components/Layout/auth.tsx index 47e75d88f..8221e0472 100644 --- a/src/components/Layout/auth.tsx +++ b/src/components/Layout/auth.tsx @@ -25,10 +25,10 @@ const Auth = ({ children }: { children: JSX.Element }) => { useQuery( [router.pathname, userInfo], () => { - setLoading(true); if (unAuthPage[router.pathname] === true || userInfo) { return setLoading(false); } else { + setLoading(true); return getTokenLogin(); } }, diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index 4cbea772c..7641a77f4 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -43,15 +43,13 @@ const navbarList = [ const Layout = ({ children }: { children: JSX.Element }) => { const { isPc } = useScreen(); const router = useRouter(); - const { Loading } = useLoading({ - defaultLoading: true - }); + const { Loading } = useLoading({ defaultLoading: true }); const { loading } = useGlobalStore(); return ( <> {!unShowLayoutRoute[router.pathname] ? ( - + {isPc ? ( <> diff --git a/src/hooks/useLoading.tsx b/src/hooks/useLoading.tsx index 68c4d3808..d50ede065 100644 --- a/src/hooks/useLoading.tsx +++ b/src/hooks/useLoading.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, memo } from 'react'; import { Spinner, Flex } from '@chakra-ui/react'; export const useLoading = (props?: { defaultLoading: boolean }) => { @@ -31,6 +31,6 @@ export const useLoading = (props?: { defaultLoading: boolean }) => { return { isLoading, setIsLoading, - Loading + Loading: memo(Loading) }; }; diff --git a/src/hooks/useScreen.ts b/src/hooks/useScreen.ts index 4f96861d0..c392aff3c 100644 --- a/src/hooks/useScreen.ts +++ b/src/hooks/useScreen.ts @@ -11,6 +11,6 @@ export function useScreen() { isPc, mediaLgMd: useMemo(() => (isPc ? 'lg' : 'md'), [isPc]), mediaMdSm: useMemo(() => (isPc ? 'md' : 'sm'), [isPc]), - media: (pc: number | string, phone: number | string) => (isPc ? pc : phone) + media: (pc: any, phone: any) => (isPc ? pc : phone) }; } diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 375bcd771..9596b4ab3 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -38,6 +38,7 @@ export default function App({ Component, pageProps }: AppProps) { /> + @@ -45,7 +46,6 @@ export default function App({ Component, pageProps }: AppProps) { - ); } diff --git a/src/pages/chat/index.tsx b/src/pages/chat/index.tsx index 62b350a7a..07aee91a8 100644 --- a/src/pages/chat/index.tsx +++ b/src/pages/chat/index.tsx @@ -13,10 +13,13 @@ import { Textarea, Box, Flex, Button } from '@chakra-ui/react'; import { useToast } from '@/hooks/useToast'; import Icon from '@/components/Icon'; import { useScreen } from '@/hooks/useScreen'; -import Markdown from '@/components/Markdown'; import { useQuery } from '@tanstack/react-query'; import { useLoading } from '@/hooks/useLoading'; import { OpenAiModelEnum } from '@/constants/model'; +import dynamic from 'next/dynamic'; +import { useGlobalStore } from '@/store/global'; + +const Markdown = dynamic(() => import('@/components/Markdown')); const textareaMinH = '22px'; @@ -34,7 +37,7 @@ const Chat = () => { const isChatting = useMemo(() => chatList[chatList.length - 1]?.status === 'loading', [chatList]); const lastWordHuman = useMemo(() => chatList[chatList.length - 1]?.obj === 'Human', [chatList]); - const { Loading, setIsLoading } = useLoading({ defaultLoading: true }); + const { setLoading } = useGlobalStore(); // 滚动到底部 const scrollToBottom = useCallback(() => { @@ -49,32 +52,40 @@ const Chat = () => { }, []); // 初始化聊天框 - useQuery([chatId, windowId], () => (chatId ? getInitChatSiteInfo(chatId, windowId) : null), { - cacheTime: 5 * 60 * 1000, - onSuccess(res) { - if (!res) return; - router.replace(`/chat?chatId=${chatId}&windowId=${res.windowId}`); - - setChatSiteData(res.chatSite); - setChatList( - res.history.map((item) => ({ - ...item, - status: 'finish' - })) - ); - scrollToBottom(); - setIsLoading(false); + useQuery( + [chatId, windowId], + () => { + if (!chatId) return null; + setLoading(true); + return getInitChatSiteInfo(chatId, windowId); }, - onError() { - toast({ - title: '初始化异常,请刷新', - status: 'error', - isClosable: true, - duration: 5000 - }); - setIsLoading(false); + { + cacheTime: 5 * 60 * 1000, + onSuccess(res) { + if (!res) return; + router.replace(`/chat?chatId=${chatId}&windowId=${res.windowId}`); + + setChatSiteData(res.chatSite); + setChatList( + res.history.map((item) => ({ + ...item, + status: 'finish' + })) + ); + scrollToBottom(); + setLoading(false); + }, + onError() { + toast({ + title: '初始化异常,请刷新', + status: 'error', + isClosable: true, + duration: 5000 + }); + setLoading(false); + } } - }); + ); // gpt3 方法 const gpt3ChatPrompt = useCallback( @@ -293,7 +304,7 @@ const Chat = () => { alt="/imgs/modelAvatar.png" width={30} height={30} - > + /> {item.obj === 'AI' ? ( @@ -393,7 +404,6 @@ const Chat = () => { )} - ); }; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 5bfc70f2e..75046b298 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,12 +1,9 @@ -import React, { useEffect } from 'react'; -import { useRouter } from 'next/router'; -import { Card, Text, Box, Heading, Flex } from '@chakra-ui/react'; +import React from 'react'; +import { Card } from '@chakra-ui/react'; import Markdown from '@/components/Markdown'; import { introPage } from '@/constants/common'; const Home = () => { - const router = useRouter(); - return ( diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index 18fe7d487..39ae9c5e3 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -1,15 +1,17 @@ -import React, { useState, useCallback } from 'react'; +import React, { useState, useCallback, useMemo } from 'react'; import styles from './index.module.scss'; import { Box, Flex, Image } from '@chakra-ui/react'; import { PageTypeEnum } from '@/constants/user'; -import LoginForm from './components/LoginForm'; -import RegisterForm from './components/RegisterForm'; -import ForgetPasswordForm from './components/ForgetPasswordForm'; import { useScreen } from '@/hooks/useScreen'; import type { ResLogin } from '@/api/response/user'; import { useRouter } from 'next/router'; import { useUserStore } from '@/store/user'; +import dynamic from 'next/dynamic'; +const LoginForm = dynamic(() => import('./components/LoginForm')); +const RegisterForm = dynamic(() => import('./components/RegisterForm')); +const ForgetPasswordForm = dynamic(() => import('./components/ForgetPasswordForm')); + const Login = () => { const router = useRouter(); const { isPc } = useScreen(); @@ -24,20 +26,17 @@ const Login = () => { [router, setUserInfo] ); - const map = { - [PageTypeEnum.login]: { - Component: , - img: '/icon/loginLeft.svg' - }, - [PageTypeEnum.register]: { - Component: , - img: '/icon/loginLeft.svg' - }, - [PageTypeEnum.forgetPassword]: { - Component: , - img: '/icon/loginLeft.svg' - } - }; + function DynamicComponent({ type }: { type: `${PageTypeEnum}` }) { + const TypeMap = { + [PageTypeEnum.login]: LoginForm, + [PageTypeEnum.register]: RegisterForm, + [PageTypeEnum.forgetPassword]: ForgetPasswordForm + }; + + const Component = TypeMap[type]; + + return ; + } return ( @@ -54,7 +53,7 @@ const Login = () => { > {isPc && ( { px={10} borderRadius={isPc ? 'md' : 'none'} > - {map[pageType].Component} + diff --git a/src/pages/model/components/CreateModel.tsx b/src/pages/model/components/CreateModel.tsx index 5dc75dd78..4bcb27d07 100644 --- a/src/pages/model/components/CreateModel.tsx +++ b/src/pages/model/components/CreateModel.tsx @@ -25,11 +25,9 @@ interface CreateFormType { } const CreateModel = ({ - isOpen, setCreateModelOpen, onSuccess }: { - isOpen: boolean; setCreateModelOpen: Dispatch; onSuccess: Dispatch; }) => { @@ -72,7 +70,7 @@ const CreateModel = ({ return ( <> - setCreateModelOpen(false)}> + setCreateModelOpen(false)}> 创建模型 diff --git a/src/pages/model/components/ModelEditForm.tsx b/src/pages/model/components/ModelEditForm.tsx index 4cb6d7ff1..a4206562d 100644 --- a/src/pages/model/components/ModelEditForm.tsx +++ b/src/pages/model/components/ModelEditForm.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect, useRef } from 'react'; import { Grid, Box, Card, Flex, Button, FormControl, Input, Textarea } from '@chakra-ui/react'; import type { ModelType } from '@/types/model'; import { useForm } from 'react-hook-form'; @@ -7,17 +7,17 @@ import { putModelById } from '@/api/model'; import { useScreen } from '@/hooks/useScreen'; import { useGlobalStore } from '@/store/global'; -const ModelEditForm = ({ model }: { model: ModelType }) => { +const ModelEditForm = ({ model }: { model?: ModelType }) => { + const isInit = useRef(false); const { register, handleSubmit, + reset, formState: { errors } - } = useForm({ - defaultValues: model - }); + } = useForm(); const { setLoading } = useGlobalStore(); const { toast } = useToast(); - const { isPc } = useScreen(); + const { media } = useScreen(); const onclickSave = useCallback( async (data: ModelType) => { @@ -61,8 +61,16 @@ const ModelEditForm = ({ model }: { model: ModelType }) => { }); }, [errors, toast]); + /* model 只会改变一次 */ + useEffect(() => { + if (model && !isInit.current) { + reset(model); + isInit.current = true; + } + }, [model, reset]); + return ( - + @@ -83,7 +91,7 @@ const ModelEditForm = ({ model }: { model: ModelType }) => { 对话模型: - {model.service.modelName} + {model?.service.modelName} diff --git a/src/pages/model/components/Training.tsx b/src/pages/model/components/Training.tsx index f60879d74..54ceaf59c 100644 --- a/src/pages/model/components/Training.tsx +++ b/src/pages/model/components/Training.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useCallback, useState } from 'react'; -import { Box, Card, TableContainer, Table, Thead, Tbody, Tr, Th, Td } from '@chakra-ui/react'; +import { Box, TableContainer, Table, Thead, Tbody, Tr, Th, Td } from '@chakra-ui/react'; import { ModelType } from '@/types/model'; import { getModelTrainings } from '@/api/model'; import type { TrainingItemType } from '@/types/training'; @@ -38,7 +38,7 @@ const Training = ({ model }: { model: ModelType }) => { }, [loadTrainingRecords, model]); return ( - + <> 训练记录: {model.trainingTimes}次 @@ -63,7 +63,7 @@ const Training = ({ model }: { model: ModelType }) => { - + ); }; diff --git a/src/pages/model/detail.tsx b/src/pages/model/detail.tsx index a23c7848a..99ad610bb 100644 --- a/src/pages/model/detail.tsx +++ b/src/pages/model/detail.tsx @@ -11,12 +11,14 @@ import { useGlobalStore } from '@/store/global'; import { useScreen } from '@/hooks/useScreen'; import ModelEditForm from './components/ModelEditForm'; import Icon from '@/components/Icon'; -import Training from './components/Training'; +import dynamic from 'next/dynamic'; + +const Training = dynamic(() => import('./components/Training')); const ModelDetail = () => { const { toast } = useToast(); const router = useRouter(); - const { isPc } = useScreen(); + const { isPc, media } = useScreen(); const { setLoading } = useGlobalStore(); const { openConfirm, ConfirmChild } = useConfirm({ content: '确认删除该模型?' @@ -128,114 +130,114 @@ const ModelDetail = () => { return ( <> - {!!model && ( - <> - {/* 头部 */} - - {isPc ? ( - - - {model.name} 配置 - - + {/* 头部 */} + + {isPc ? ( + + + {model?.name || '模型'} 配置 + + {!!model && ( + + {formatModelStatus[model.status].text} + + )} + + + + ) : ( + <> + + + {model?.name || '模型'} 配置 + + {!!model && ( + {formatModelStatus[model.status].text} - - - - ) : ( - <> - - - {model.name} 配置 - - - {formatModelStatus[model.status].text} - - - - - - - )} - - {/* 基本信息编辑 */} - - + )} + + + + + + )} + + {/* 基本信息编辑 */} + + + + {/* 其他配置 */} + + {!!model && } + + + 神奇操作 - {/* 其他配置 */} - - - - - 神奇操作 - - - 模型微调: - - - - 下载模板 - - - {/* 提示 */} - - - 每行包括一个 prompt 和一个 completion - - - prompt 必须以 \n\n###\n\n 结尾,且尽量保障每个 prompt - 内容不都是同一个标点结尾,可以加一个空格打断相同性, - - - completion 开头必须有一个空格,末尾必须以 ### 结尾,同样的不要都是同一个标点结尾。 - - - - 删除模型: - - - - - - )} + + 模型微调: + + + + 下载模板 + + + {/* 提示 */} + + + 每行包括一个 prompt 和一个 completion + + + prompt 必须以 \n\n###\n\n 结尾,且尽量保障每个 prompt + 内容不都是同一个标点结尾,可以加一个空格打断相同性, + + + completion 开头必须有一个空格,末尾必须以 ### 结尾,同样的不要都是同一个标点结尾。 + + + + 删除模型: + + + + diff --git a/src/pages/model/list.tsx b/src/pages/model/list.tsx index 525e9b213..607435443 100644 --- a/src/pages/model/list.tsx +++ b/src/pages/model/list.tsx @@ -1,15 +1,17 @@ -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useState, useCallback } from 'react'; import { Box, Button, Flex, Card } from '@chakra-ui/react'; import { getMyModels } from '@/api/model'; import { getChatSiteId } from '@/api/chat'; import { ModelType } from '@/types/model'; -import CreateModel from './components/CreateModel'; import { useRouter } from 'next/router'; import ModelTable from './components/ModelTable'; import ModelPhoneList from './components/ModelPhoneList'; import { useScreen } from '@/hooks/useScreen'; import { useQuery } from '@tanstack/react-query'; import { useLoading } from '@/hooks/useLoading'; +import dynamic from 'next/dynamic'; + +const CreateModel = dynamic(() => import('./components/CreateModel')); const ModelList = () => { const { isPc } = useScreen(); @@ -72,11 +74,10 @@ const ModelList = () => { )} {/* 创建弹窗 */} - + {openCreateModel && ( + + )} + );