### What problem does this PR solve? some chunk method pictures are not in English #437 feat: set the height of both html and body to 100% feat: add SharedChat feat: add shared hooks ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
50
web/src/pages/chat/share/index.less
Normal file
50
web/src/pages/chat/share/index.less
Normal file
@@ -0,0 +1,50 @@
|
||||
.chatWrapper {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.chatContainer {
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
.messageContainer {
|
||||
overflow-y: auto;
|
||||
padding-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.messageItem {
|
||||
padding: 24px 0;
|
||||
.messageItemSection {
|
||||
display: inline-block;
|
||||
}
|
||||
.messageItemSectionLeft {
|
||||
width: 70%;
|
||||
}
|
||||
.messageItemSectionRight {
|
||||
width: 40%;
|
||||
}
|
||||
.messageItemContent {
|
||||
display: inline-flex;
|
||||
gap: 20px;
|
||||
}
|
||||
.messageItemContentReverse {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
.messageText {
|
||||
.chunkText();
|
||||
padding: 0 14px;
|
||||
background-color: rgba(249, 250, 251, 1);
|
||||
word-break: break-all;
|
||||
}
|
||||
.messageEmpty {
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
.messageItemLeft {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.messageItemRight {
|
||||
text-align: right;
|
||||
}
|
||||
53
web/src/pages/chat/share/index.tsx
Normal file
53
web/src/pages/chat/share/index.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import { useEffect } from 'react';
|
||||
import {
|
||||
useCreateSharedConversationOnMount,
|
||||
useSelectCurrentSharedConversation,
|
||||
useSendSharedMessage,
|
||||
} from '../shared-hooks';
|
||||
import ChatContainer from './large';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
const SharedChat = () => {
|
||||
const { conversationId } = useCreateSharedConversationOnMount();
|
||||
const {
|
||||
currentConversation,
|
||||
addNewestConversation,
|
||||
removeLatestMessage,
|
||||
ref,
|
||||
loading,
|
||||
setCurrentConversation,
|
||||
} = useSelectCurrentSharedConversation(conversationId);
|
||||
|
||||
const {
|
||||
handlePressEnter,
|
||||
handleInputChange,
|
||||
value,
|
||||
loading: sendLoading,
|
||||
} = useSendSharedMessage(
|
||||
currentConversation,
|
||||
addNewestConversation,
|
||||
removeLatestMessage,
|
||||
setCurrentConversation,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
console.info(location.href);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.chatWrapper}>
|
||||
<ChatContainer
|
||||
value={value}
|
||||
handleInputChange={handleInputChange}
|
||||
handlePressEnter={handlePressEnter}
|
||||
loading={loading}
|
||||
sendLoading={sendLoading}
|
||||
conversation={currentConversation}
|
||||
ref={ref}
|
||||
></ChatContainer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SharedChat;
|
||||
122
web/src/pages/chat/share/large.tsx
Normal file
122
web/src/pages/chat/share/large.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg';
|
||||
import { MessageType } from '@/constants/chat';
|
||||
import { useTranslate } from '@/hooks/commonHooks';
|
||||
import { Message } from '@/interfaces/database/chat';
|
||||
import { Avatar, Button, Flex, Input, Skeleton, Spin } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { useSelectConversationLoading } from '../hooks';
|
||||
|
||||
import React, { ChangeEventHandler, forwardRef } from 'react';
|
||||
import { IClientConversation } from '../interface';
|
||||
import styles from './index.less';
|
||||
import SharedMarkdown from './shared-markdown';
|
||||
|
||||
const MessageItem = ({ item }: { item: Message }) => {
|
||||
const isAssistant = item.role === MessageType.Assistant;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.messageItem, {
|
||||
[styles.messageItemLeft]: item.role === MessageType.Assistant,
|
||||
[styles.messageItemRight]: item.role === MessageType.User,
|
||||
})}
|
||||
>
|
||||
<section
|
||||
className={classNames(styles.messageItemSection, {
|
||||
[styles.messageItemSectionLeft]: item.role === MessageType.Assistant,
|
||||
[styles.messageItemSectionRight]: item.role === MessageType.User,
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={classNames(styles.messageItemContent, {
|
||||
[styles.messageItemContentReverse]: item.role === MessageType.User,
|
||||
})}
|
||||
>
|
||||
{item.role === MessageType.User ? (
|
||||
<Avatar
|
||||
size={40}
|
||||
src={
|
||||
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<AssistantIcon></AssistantIcon>
|
||||
)}
|
||||
<Flex vertical gap={8} flex={1}>
|
||||
<b>{isAssistant ? '' : 'You'}</b>
|
||||
<div className={styles.messageText}>
|
||||
{item.content !== '' ? (
|
||||
<SharedMarkdown content={item.content}></SharedMarkdown>
|
||||
) : (
|
||||
<Skeleton active className={styles.messageEmpty} />
|
||||
)}
|
||||
</div>
|
||||
</Flex>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface IProps {
|
||||
handlePressEnter(): void;
|
||||
handleInputChange: ChangeEventHandler<HTMLInputElement>;
|
||||
value: string;
|
||||
loading: boolean;
|
||||
sendLoading: boolean;
|
||||
conversation: IClientConversation;
|
||||
ref: React.LegacyRef<any>;
|
||||
}
|
||||
|
||||
const ChatContainer = (
|
||||
{
|
||||
handlePressEnter,
|
||||
handleInputChange,
|
||||
value,
|
||||
loading: sendLoading,
|
||||
conversation,
|
||||
}: IProps,
|
||||
ref: React.LegacyRef<any>,
|
||||
) => {
|
||||
const loading = useSelectConversationLoading();
|
||||
const { t } = useTranslate('chat');
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex flex={1} className={styles.chatContainer} vertical>
|
||||
<Flex flex={1} vertical className={styles.messageContainer}>
|
||||
<div>
|
||||
<Spin spinning={loading}>
|
||||
{conversation?.message?.map((message) => {
|
||||
return (
|
||||
<MessageItem key={message.id} item={message}></MessageItem>
|
||||
);
|
||||
})}
|
||||
</Spin>
|
||||
</div>
|
||||
<div ref={ref} />
|
||||
</Flex>
|
||||
<Input
|
||||
size="large"
|
||||
placeholder={t('sendPlaceholder')}
|
||||
value={value}
|
||||
// disabled={disabled}
|
||||
suffix={
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handlePressEnter}
|
||||
loading={sendLoading}
|
||||
// disabled={disabled}
|
||||
>
|
||||
{t('send')}
|
||||
</Button>
|
||||
}
|
||||
onPressEnter={handlePressEnter}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default forwardRef(ChatContainer);
|
||||
32
web/src/pages/chat/share/shared-markdown.tsx
Normal file
32
web/src/pages/chat/share/shared-markdown.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import Markdown from 'react-markdown';
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
|
||||
const SharedMarkdown = ({ content }: { content: string }) => {
|
||||
return (
|
||||
<Markdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
components={
|
||||
{
|
||||
code(props: any) {
|
||||
const { children, className, node, ...rest } = props;
|
||||
const match = /language-(\w+)/.exec(className || '');
|
||||
return match ? (
|
||||
<SyntaxHighlighter {...rest} PreTag="div" language={match[1]}>
|
||||
{String(children).replace(/\n$/, '')}
|
||||
</SyntaxHighlighter>
|
||||
) : (
|
||||
<code {...rest} className={className}>
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
},
|
||||
} as any
|
||||
}
|
||||
>
|
||||
{content}
|
||||
</Markdown>
|
||||
);
|
||||
};
|
||||
|
||||
export default SharedMarkdown;
|
||||
Reference in New Issue
Block a user