feat: Add Skeleton to MessageItem before the backend returns a message and fixed the issue where ChatConfigurationModal displays old data when creating a new dialog (#99)

* feat: fixed the issue where ChatConfigurationModal displays old data when creating a new dialog

* feat: Add Skeleton to MessageItem before the backend returns a message
This commit is contained in:
balibabu 2024-03-05 19:28:44 +08:00 committed by GitHub
parent 602038ac49
commit 8b2bbd79e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 117 additions and 72 deletions

View File

@ -18,7 +18,7 @@ export default defineConfig({
dva: {},
lessLoader: {
modifyVars: {
hack: `true; @import "~@/less/variable.less";`,
hack: `true; @import "~@/less/index.less";`,
},
},
proxy: {

View File

@ -1,5 +1,4 @@
import { ReactComponent as StarIon } from '@/assets/svg/chat-star.svg';
import { ReactComponent as FileIcon } from '@/assets/svg/file-management.svg';
import { ReactComponent as KnowledgeBaseIcon } from '@/assets/svg/knowledge-base.svg';
import { ReactComponent as Logo } from '@/assets/svg/logo.svg';
import { Layout, Radio, Space, theme } from 'antd';
@ -23,7 +22,7 @@ const RagHeader = () => {
() => [
{ path: '/knowledge', name: 'Knowledge Base', icon: KnowledgeBaseIcon },
{ path: '/chat', name: 'Chat', icon: StarIon },
{ path: '/file', name: 'File Management', icon: FileIcon },
// { path: '/file', name: 'File Management', icon: FileIcon },
],
[],
);

2
web/src/less/index.less Normal file
View File

@ -0,0 +1,2 @@
@import './variable.less';
@import './mixins.less';

31
web/src/less/mixins.less Normal file
View File

@ -0,0 +1,31 @@
.chunkText() {
em {
color: red;
font-style: normal;
}
table {
width: 100%;
}
caption {
color: @blurBackground;
font-size: 20px;
height: 50px;
line-height: 50px;
font-weight: 600;
margin-bottom: 10px;
}
th {
color: #fff;
background-color: @blurBackground;
}
td:hover {
background: @blurBackgroundHover;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
}

View File

@ -9,35 +9,7 @@
.content {
flex: 1;
em {
color: red;
font-style: normal;
}
table {
width: 100%;
}
caption {
color: @blurBackground;
font-size: 20px;
height: 50px;
line-height: 50px;
font-weight: 600;
margin-bottom: 10px;
}
th {
color: #fff;
background-color: @blurBackground;
}
td:hover {
background: @blurBackgroundHover;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
.chunkText;
}
.cardSelected {

View File

@ -121,14 +121,16 @@ const ChatConfigurationModal = ({ visible, hideModal, id }: IProps) => {
);
useEffect(() => {
const icon = currentDialog.icon;
let fileList: UploadFile[] = [];
if (visible) {
const icon = currentDialog.icon;
let fileList: UploadFile[] = [];
if (icon) {
fileList = [{ uid: '1', name: 'file', thumbUrl: icon, status: 'done' }];
if (icon) {
fileList = [{ uid: '1', name: 'file', thumbUrl: icon, status: 'done' }];
}
form.setFieldsValue({ ...currentDialog, icon: fileList });
}
form.setFieldsValue({ ...currentDialog, icon: fileList });
}, [currentDialog, form]);
}, [currentDialog, form, visible]);
return (
<Modal

View File

@ -28,6 +28,9 @@
padding: 0 14px;
background-color: rgba(249, 250, 251, 1);
}
.messageEmpty {
width: 300px;
}
.referenceIcon {
padding: 0 6px;
}
@ -52,3 +55,6 @@
.referenceImagePreview {
width: 600px;
}
.chunkContentText {
.chunkText;
}

View File

@ -11,6 +11,7 @@ import {
Input,
List,
Popover,
Skeleton,
Space,
} from 'antd';
import classNames from 'classnames';
@ -100,7 +101,12 @@ const MessageItem = ({
></Image>
</Popover>
<Space direction={'vertical'}>
<div>{chunkItem?.content_with_weight}</div>
<div
dangerouslySetInnerHTML={{
__html: chunkItem?.content_with_weight,
}}
className={styles.chunkContentText}
></div>
{documentId && (
<Flex gap={'middle'}>
<img src={fileThumbnails[documentId]} alt="" />
@ -171,17 +177,24 @@ const MessageItem = ({
<Flex vertical gap={8} flex={1}>
<b>{isAssistant ? '' : userInfo.nickname}</b>
<div className={styles.messageText}>
<Markdown
rehypePlugins={[rehypeWrapReference]}
components={
{
'custom-typography': ({ children }: { children: string }) =>
renderReference(children),
} as any
}
>
{item.content}
</Markdown>
{item.content ? (
<Markdown
rehypePlugins={[rehypeWrapReference]}
components={
{
'custom-typography': ({
children,
}: {
children: string;
}) => renderReference(children),
} as any
}
>
{item.content}
</Markdown>
) : (
<Skeleton active className={styles.messageEmpty} />
)}
</div>
{isAssistant && referenceDocumentList.length > 0 && (
<List

View File

@ -78,12 +78,10 @@ export const useSetCurrentDialog = () => {
const setCurrentDialog = useCallback(
(dialogId: string) => {
if (dialogId) {
dispatch({
type: 'chatModel/setCurrentDialog',
payload: { id: dialogId },
});
}
dispatch({
type: 'chatModel/setCurrentDialog',
payload: { id: dialogId },
});
},
[dispatch],
);
@ -427,6 +425,12 @@ export const useSelectCurrentConversation = () => {
content: message,
id: uuid(),
} as IMessage,
{
role: MessageType.Assistant,
content: '',
id: uuid(),
reference: [],
} as IMessage,
],
};
});
@ -525,12 +529,13 @@ export const useSendMessage = () => {
const conversation: IClientConversation = useSelector(
(state: any) => state.chatModel.currentConversation,
);
const fetchConversation = useFetchConversation();
const { handleClickConversation } = useClickConversationCard();
const sendMessage = useCallback(
(message: string, id?: string) => {
dispatch({
async (message: string, id?: string) => {
const retcode = await dispatch<any>({
type: 'chatModel/completeConversation',
payload: {
conversation_id: id ?? conversationId,
@ -545,8 +550,22 @@ export const useSendMessage = () => {
],
},
});
if (retcode === 0) {
if (id) {
handleClickConversation(id);
} else {
fetchConversation(conversationId);
}
}
},
[dispatch, conversation?.message, conversationId],
[
dispatch,
conversation?.message,
conversationId,
fetchConversation,
handleClickConversation,
],
);
const handleSendMessage = useCallback(
@ -557,12 +576,11 @@ export const useSendMessage = () => {
const data = await setConversation(message);
if (data.retcode === 0) {
const id = data.data.id;
handleClickConversation(id);
sendMessage(message, id);
}
}
},
[conversationId, handleClickConversation, setConversation, sendMessage],
[conversationId, setConversation, sendMessage],
);
return { sendMessage: handleSendMessage };

View File

@ -38,6 +38,7 @@
.chatTitleContent {
padding: 5px 10px;
overflow: auto;
}
.chatTitleCard {

View File

@ -76,9 +76,9 @@ const Chat = () => {
(info: any) => {
info?.domEvent?.preventDefault();
info?.domEvent?.stopPropagation();
if (dialogId) {
setCurrentDialog(dialogId);
}
// if (dialogId) {
setCurrentDialog(dialogId ?? '');
// }
showModal();
};

View File

@ -140,14 +140,15 @@ const model: DvaModel<ChatModelState> = {
},
*completeConversation({ payload }, { call, put }) {
const { data } = yield call(chatService.completeConversation, payload);
if (data.retcode === 0) {
yield put({
type: 'getConversation',
payload: {
conversation_id: payload.conversation_id,
},
});
}
// if (data.retcode === 0) {
// yield put({
// type: 'getConversation',
// payload: {
// conversation_id: payload.conversation_id,
// },
// });
// }
return data.retcode;
},
*removeConversation({ payload }, { call, put }) {
const { data } = yield call(chatService.removeConversation, {