mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-03 21:48:02 +00:00
perf: guide modules
This commit is contained in:
@@ -8,8 +8,8 @@ const Avatar = ({ w = '30px', ...props }: ImageProps) => {
|
||||
<Image
|
||||
fallbackSrc={LOGO_ICON}
|
||||
fallbackStrategy={'onError'}
|
||||
borderRadius={'50%'}
|
||||
objectFit={'cover'}
|
||||
borderRadius={'md'}
|
||||
objectFit={'contain'}
|
||||
alt=""
|
||||
w={w}
|
||||
h={w}
|
||||
|
@@ -25,7 +25,7 @@ import {
|
||||
} from '@/utils/tools';
|
||||
import { Box, Card, Flex, Input, Textarea, Button, useTheme, BoxProps } from '@chakra-ui/react';
|
||||
import { feConfigs } from '@/store/static';
|
||||
import { EventNameEnum } from '../Markdown/constant';
|
||||
import { event } from '@/utils/plugin/eventbus';
|
||||
|
||||
import { adaptChatItem_openAI } from '@/utils/plugin/openai';
|
||||
import { useMarkdown } from '@/hooks/useMarkdown';
|
||||
@@ -474,6 +474,16 @@ const ChatBox = (
|
||||
};
|
||||
}, [router.query]);
|
||||
|
||||
useEffect(() => {
|
||||
event.on('guideClick', ({ text }: { text: string }) => {
|
||||
if (!text) return;
|
||||
handleSubmit((data) => sendPrompt(data, text))();
|
||||
});
|
||||
|
||||
return () => {
|
||||
event.off('guideClick');
|
||||
};
|
||||
}, [handleSubmit, sendPrompt]);
|
||||
useEffect(() => {
|
||||
const listen = () => {
|
||||
cancelBroadcast();
|
||||
@@ -497,15 +507,7 @@ const ChatBox = (
|
||||
<ChatAvatar src={appAvatar} type={'AI'} />
|
||||
{/* message */}
|
||||
<Card order={2} mt={2} {...MessageCardStyle} bg={'white'} maxW={messageCardMaxW}>
|
||||
<Markdown
|
||||
source={`~~~guide \n${welcomeText}`}
|
||||
isChatting={false}
|
||||
onClick={(e) => {
|
||||
const val = e?.data;
|
||||
if (e?.event !== EventNameEnum.guideClick || !val) return;
|
||||
handleSubmit((data) => sendPrompt(data, val))();
|
||||
}}
|
||||
/>
|
||||
<Markdown source={`~~~guide \n${welcomeText}`} isChatting={false} />
|
||||
</Card>
|
||||
</Flex>
|
||||
)}
|
||||
|
@@ -106,7 +106,13 @@ const Navbar = ({ unread }: { unread: number }) => {
|
||||
cursor={'pointer'}
|
||||
onClick={() => router.push('/account')}
|
||||
>
|
||||
<Avatar w={'36px'} h={'36px'} src={userInfo?.avatar} fallbackSrc={HUMAN_ICON} />
|
||||
<Avatar
|
||||
w={'36px'}
|
||||
h={'36px'}
|
||||
borderRadius={'none'}
|
||||
src={userInfo?.avatar}
|
||||
fallbackSrc={HUMAN_ICON}
|
||||
/>
|
||||
</Box>
|
||||
{/* 导航列表 */}
|
||||
<Box flex={1}>
|
||||
|
@@ -4,13 +4,37 @@ import ReactMarkdown from 'react-markdown';
|
||||
import RemarkGfm from 'remark-gfm';
|
||||
import RemarkMath from 'remark-math';
|
||||
import RehypeKatex from 'rehype-katex';
|
||||
import { event } from '@/utils/plugin/eventbus';
|
||||
|
||||
import 'katex/dist/katex.min.css';
|
||||
import styles from '../index.module.scss';
|
||||
import { EventNameEnum } from '../constant';
|
||||
import Image from '../img/Image';
|
||||
|
||||
const Guide = ({ text, onClick }: { text: string; onClick?: (e: any) => void }) => {
|
||||
const formatText = useMemo(() => text.replace(/\[(.*?)\]/g, '[$1]()'), [text]);
|
||||
function Link(e: any) {
|
||||
const href = e.href;
|
||||
const text = String(e.children);
|
||||
return (
|
||||
<Box as={'li'} py={1} m={0}>
|
||||
<Box
|
||||
as={'span'}
|
||||
color={'blue.600'}
|
||||
textDecoration={'underline'}
|
||||
cursor={'pointer'}
|
||||
onClick={() => {
|
||||
if (href) {
|
||||
return window.open(href, '_blank');
|
||||
}
|
||||
event.emit('guideClick', { text });
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const Guide = ({ text }: { text: string }) => {
|
||||
const formatText = useMemo(() => text.replace(/\[(.*?)\]($|\n)/g, '[$1]()\n'), [text]);
|
||||
|
||||
return (
|
||||
<ReactMarkdown
|
||||
@@ -18,27 +42,8 @@ const Guide = ({ text, onClick }: { text: string; onClick?: (e: any) => void })
|
||||
remarkPlugins={[RemarkGfm, RemarkMath]}
|
||||
rehypePlugins={[RehypeKatex]}
|
||||
components={{
|
||||
a({ children }: any) {
|
||||
return (
|
||||
<Box as={'li'} py={1} m={0}>
|
||||
<Box
|
||||
as={'span'}
|
||||
color={'blue.600'}
|
||||
textDecoration={'underline'}
|
||||
cursor={'pointer'}
|
||||
onClick={() => {
|
||||
if (!onClick) return;
|
||||
onClick({
|
||||
event: EventNameEnum.guideClick,
|
||||
data: String(children)
|
||||
});
|
||||
}}
|
||||
>
|
||||
{String(children)}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
a: Link,
|
||||
img: Image
|
||||
}}
|
||||
>
|
||||
{formatText}
|
||||
|
@@ -1,3 +0,0 @@
|
||||
export enum EventNameEnum {
|
||||
guideClick = 'guideClick'
|
||||
}
|
@@ -22,6 +22,7 @@ const MdImage = ({ src }: { src?: string }) => {
|
||||
fallbackStrategy={'onError'}
|
||||
cursor={succeed ? 'pointer' : 'default'}
|
||||
loading="eager"
|
||||
objectFit={'contain'}
|
||||
onLoad={() => {
|
||||
setIsLoading(false);
|
||||
setSucceed(true);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import RemarkGfm from 'remark-gfm';
|
||||
import RemarkMath from 'remark-math';
|
||||
@@ -15,7 +15,7 @@ const MermaidCodeBlock = dynamic(() => import('./img/MermaidCodeBlock'));
|
||||
const MdImage = dynamic(() => import('./img/Image'));
|
||||
const ChatGuide = dynamic(() => import('./chat/Guide'));
|
||||
|
||||
function Code({ inline, className, children, onClick }: any) {
|
||||
function Code({ inline, className, children }: any) {
|
||||
const match = /language-(\w+)/.exec(className || '');
|
||||
const codeType = match?.[1];
|
||||
|
||||
@@ -24,7 +24,7 @@ function Code({ inline, className, children, onClick }: any) {
|
||||
}
|
||||
|
||||
if (codeType === 'guide') {
|
||||
return <ChatGuide text={String(children)} onClick={onClick} />;
|
||||
return <ChatGuide text={String(children)} />;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -33,28 +33,19 @@ function Code({ inline, className, children, onClick }: any) {
|
||||
</CodeLight>
|
||||
);
|
||||
}
|
||||
|
||||
function Image({ src }: { src?: string }) {
|
||||
return <MdImage src={src} />;
|
||||
}
|
||||
|
||||
const Markdown = ({
|
||||
source,
|
||||
isChatting = false,
|
||||
onClick
|
||||
}: {
|
||||
source: string;
|
||||
isChatting?: boolean;
|
||||
onClick?: (e: any) => void;
|
||||
}) => {
|
||||
const Markdown = ({ source, isChatting = false }: { source: string; isChatting?: boolean }) => {
|
||||
const components = useMemo(
|
||||
() => ({
|
||||
img: Image,
|
||||
pre: 'div',
|
||||
p: 'div',
|
||||
code: (props: any) => <Code {...props} onClick={onClick} />
|
||||
code: Code
|
||||
}),
|
||||
[onClick]
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@@ -53,8 +53,8 @@ export async function generateVector(): Promise<any> {
|
||||
|
||||
dataItems = [
|
||||
{
|
||||
q: data.q.replace(/[\x00-\x1F]/g, ' '),
|
||||
a: data.a.replace(/[\x00-\x1F]/g, ' ')
|
||||
q: data.q.replace(/[\x00-\x08]/g, ' '),
|
||||
a: data.a.replace(/[\x00-\x08]/g, ' ')
|
||||
}
|
||||
];
|
||||
|
||||
|
@@ -282,7 +282,7 @@ export const simpleText = (text: string) => {
|
||||
text = text.replace(/\n{2,}/g, '\n');
|
||||
text = text.replace(/\s{2,}/g, ' ');
|
||||
|
||||
text = text.replace(/[\x00-\x1F]/g, ' ');
|
||||
text = text.replace(/[\x00-\x08]/g, ' ');
|
||||
|
||||
return text;
|
||||
};
|
||||
|
18
client/src/utils/plugin/eventbus.ts
Normal file
18
client/src/utils/plugin/eventbus.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export enum EventNameEnum {
|
||||
guideClick = 'guideClick'
|
||||
}
|
||||
type EventNameType = `${EventNameEnum}`;
|
||||
|
||||
export const event = {
|
||||
list: new Map<EventNameType, Function>(),
|
||||
on: function (name: EventNameType, fn: Function) {
|
||||
this.list.set(name, fn);
|
||||
},
|
||||
emit: function (name: EventNameType, data: Record<string, any> = {}) {
|
||||
const fn = this.list.get(name);
|
||||
fn && fn(data);
|
||||
},
|
||||
off: function (name: EventNameType) {
|
||||
this.list.delete(name);
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user