feat: add avatar to MessageItem

This commit is contained in:
billchen 2024-02-26 15:03:53 +08:00
parent bc16879a10
commit 2b728f442d
8 changed files with 144 additions and 31 deletions

View file

@ -0,0 +1,22 @@
import { IUserInfo } from '@/interfaces/database/userSetting';
import { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'umi';
export const useFetchUserInfo = () => {
const dispatch = useDispatch();
const fetchUserInfo = useCallback(() => {
dispatch({ type: 'settingModel/getUserInfo' });
}, [dispatch]);
useEffect(() => {
fetchUserInfo();
}, [fetchUserInfo]);
};
export const useSelectUserInfo = () => {
const userInfo: IUserInfo = useSelector(
(state: any) => state.settingModel.userInfo,
);
return userInfo;
};

View file

@ -0,0 +1,21 @@
export interface IUserInfo {
access_token: string;
avatar?: any;
color_schema: string;
create_date: string;
create_time: number;
email: string;
id: string;
is_active: string;
is_anonymous: string;
is_authenticated: string;
is_superuser: boolean;
language: string;
last_login_time: string;
login_channel: string;
nickname: string;
password: string;
status: string;
update_date: string;
update_time: number;
}

View file

@ -19,17 +19,20 @@ const RagHeader = () => {
const navigate = useNavigate();
const { pathname } = useLocation();
const tagsData = [
{ path: '/knowledge', name: 'Knowledge Base', icon: KnowledgeBaseIcon },
{ path: '/chat', name: 'Chat', icon: StarIon },
{ path: '/file', name: 'File Management', icon: FileIcon },
];
const tagsData = useMemo(
() => [
{ path: '/knowledge', name: 'Knowledge Base', icon: KnowledgeBaseIcon },
{ path: '/chat', name: 'Chat', icon: StarIon },
{ path: '/file', name: 'File Management', icon: FileIcon },
],
[],
);
const currentPath = useMemo(() => {
return (
tagsData.find((x) => pathname.startsWith(x.path))?.name || 'knowledge'
);
}, [pathname]);
}, [pathname, tagsData]);
const handleChange = (path: string) => {
navigate(path);
@ -48,7 +51,7 @@ const RagHeader = () => {
>
<Space size={12}>
<Logo className={styles.appIcon}></Logo>
<label className={styles.appName}>Infinity flow</label>
<label className={styles.appName}>RagFlow</label>
</Space>
<Space size={[0, 8]} wrap>
<Radio.Group

View file

@ -1,3 +1,4 @@
import { useFetchUserInfo, useSelectUserInfo } from '@/hooks/userSettingHook';
import authorizationUtil from '@/utils/authorizationUtil';
import type { MenuProps } from 'antd';
import { Avatar, Button, Dropdown } from 'antd';
@ -7,6 +8,7 @@ import { history } from 'umi';
const App: React.FC = () => {
const { t } = useTranslation();
const userInfo = useSelectUserInfo();
const logout = () => {
authorizationUtil.removeAll();
@ -36,13 +38,18 @@ const App: React.FC = () => {
),
},
];
}, []);
}, [t]);
useFetchUserInfo();
return (
<Dropdown menu={{ items }} placement="bottomLeft" arrow>
<Avatar
size={32}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
src={
userInfo.avatar ??
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
}
/>
</Dropdown>
);

View file

@ -6,9 +6,26 @@
}
.messageItem {
.messageItemContent {
padding: 24px 0;
.messageItemSection {
display: inline-block;
width: 400px;
}
.messageItemSectionLeft {
width: 80%;
}
.messageItemSectionRight {
width: 20%;
}
.messageItemContent {
display: inline-flex;
gap: 20px;
}
.messageItemContentReverse {
flex-direction: row-reverse;
}
.messageText {
padding: 10px 14px;
background-color: rgba(249, 250, 251, 1);
}
}

View file

@ -1,15 +1,20 @@
import { Button, Flex, Input } from 'antd';
import { Avatar, Button, Flex, Input } from 'antd';
import { ChangeEventHandler, useState } from 'react';
import { Message } from '@/interfaces/database/chat';
import classNames from 'classnames';
import { useFetchConversation, useSendMessage } from '../hooks';
import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg';
import { MessageType } from '@/constants/chat';
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
import { IClientConversation } from '../interface';
import { useSelectUserInfo } from '@/hooks/userSettingHook';
import styles from './index.less';
const MessageItem = ({ item }: { item: Message }) => {
const userInfo = useSelectUserInfo();
return (
<div
className={classNames(styles.messageItem, {
@ -17,9 +22,38 @@ const MessageItem = ({ item }: { item: Message }) => {
[styles.messageItemRight]: item.role === MessageType.User,
})}
>
<span className={styles.messageItemContent}>
<div>{item.content}</div>
</span>
<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 ? (
userInfo.avatar ?? (
<Avatar
size={40}
src={
userInfo.avatar ??
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
}
/>
)
) : (
<AssistantIcon></AssistantIcon>
)}
<Flex vertical gap={8} flex={1}>
<b>
{item.role === MessageType.Assistant ? 'Resume Assistant' : 'You'}
</b>
<div className={styles.messageText}>{item.content}</div>
</Flex>
</div>
</section>
</div>
);
};
@ -28,9 +62,13 @@ const ChatContainer = () => {
const [value, setValue] = useState('');
const conversation: IClientConversation = useFetchConversation();
const { sendMessage } = useSendMessage();
const loading = useOneNamespaceEffectsLoading('chatModel', [
'completeConversation',
'getConversation',
]);
const handlePressEnter = () => {
console.info(value);
setValue('');
sendMessage(value);
};
@ -52,7 +90,7 @@ const ChatContainer = () => {
placeholder="Message Resume Assistant..."
value={value}
suffix={
<Button type="primary" onClick={handlePressEnter}>
<Button type="primary" onClick={handlePressEnter} loading={loading}>
Send
</Button>
}

View file

@ -426,7 +426,7 @@ export const useSendMessage = () => {
};
const handleSendMessage = async (message: string) => {
if (conversationId !== EmptyConversationId) {
if (conversationId !== '') {
sendMessage(message);
} else {
const data = await setConversation(message);

View file

@ -1,7 +1,7 @@
import { ITenantInfo } from '@/interfaces/database/knowledge';
import { IThirdOAIModelCollection as IThirdAiModelCollection } from '@/interfaces/database/llm';
import { IUserInfo } from '@/interfaces/database/userSetting';
import userService from '@/services/userService';
import authorizationUtil from '@/utils/authorizationUtil';
import { message } from 'antd';
import { Nullable } from 'typings';
import { DvaModel } from 'umi';
@ -16,6 +16,7 @@ export interface SettingModelState {
llmInfo: IThirdAiModelCollection;
myLlm: any[];
factoriesList: any[];
userInfo: IUserInfo;
}
const model: DvaModel<SettingModelState> = {
@ -30,6 +31,7 @@ const model: DvaModel<SettingModelState> = {
llmInfo: {},
myLlm: [],
factoriesList: [],
userInfo: {} as IUserInfo,
},
reducers: {
updateState(state, { payload }) {
@ -38,10 +40,11 @@ const model: DvaModel<SettingModelState> = {
...payload,
};
},
},
subscriptions: {
setup({ dispatch, history }) {
history.listen((location) => {});
setUserInfo(state, { payload }) {
return {
...state,
userInfo: payload,
};
},
},
effects: {
@ -63,15 +66,17 @@ const model: DvaModel<SettingModelState> = {
}
},
*getUserInfo({ payload = {} }, { call, put }) {
const { data, response } = yield call(userService.user_info, payload);
const { retcode, data: res, retmsg } = data;
const userInfo = {
avatar: res.avatar,
name: res.nickname,
email: res.email,
};
authorizationUtil.setUserInfo(userInfo);
const { data } = yield call(userService.user_info, payload);
const { retcode, data: res } = data;
// const userInfo = {
// avatar: res.avatar,
// name: res.nickname,
// email: res.email,
// };
// authorizationUtil.setUserInfo(userInfo);
if (retcode === 0) {
yield put({ type: 'setUserInfo', payload: res });
// localStorage.setItem('userInfo',res.)
}
},