mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-04-24 07:00:02 +08:00
fix: Fixed an issue where the first message would be displayed when sending the second message #2625 (#2626)
### What problem does this PR solve? fix: Fixed an issue where the first message would be displayed when sending the second message #2625 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [ ] New Feature (non-breaking change which adds functionality) - [ ] Documentation Update - [ ] Refactoring - [ ] Performance Improvement - [ ] Other (please describe):
This commit is contained in:
parent
34abcf7704
commit
ca2de896c7
@ -37,7 +37,9 @@ from graphrag.mind_map_extractor import MindMapExtractor
|
|||||||
def set_conversation():
|
def set_conversation():
|
||||||
req = request.json
|
req = request.json
|
||||||
conv_id = req.get("conversation_id")
|
conv_id = req.get("conversation_id")
|
||||||
if conv_id:
|
is_new = req.get("is_new")
|
||||||
|
del req["is_new"]
|
||||||
|
if not is_new:
|
||||||
del req["conversation_id"]
|
del req["conversation_id"]
|
||||||
try:
|
try:
|
||||||
if not ConversationService.update_by_id(conv_id, req):
|
if not ConversationService.update_by_id(conv_id, req):
|
||||||
@ -56,7 +58,7 @@ def set_conversation():
|
|||||||
if not e:
|
if not e:
|
||||||
return get_data_error_result(retmsg="Dialog not found")
|
return get_data_error_result(retmsg="Dialog not found")
|
||||||
conv = {
|
conv = {
|
||||||
"id": get_uuid(),
|
"id": conv_id,
|
||||||
"dialog_id": req["dialog_id"],
|
"dialog_id": req["dialog_id"],
|
||||||
"name": req.get("name", "New conversation"),
|
"name": req.get("name", "New conversation"),
|
||||||
"message": [{"role": "assistant", "content": dia.prompt_config["prologue"]}]
|
"message": [{"role": "assistant", "content": dia.prompt_config["prologue"]}]
|
||||||
|
@ -30,7 +30,7 @@ export default defineConfig({
|
|||||||
copy: ['src/conf.json'],
|
copy: ['src/conf.json'],
|
||||||
proxy: {
|
proxy: {
|
||||||
'/v1': {
|
'/v1': {
|
||||||
target: 'http://127.0.0.1:9456/',
|
target: 'http://127.0.0.1:9380/',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
ws: true,
|
ws: true,
|
||||||
logger: console,
|
logger: console,
|
||||||
|
@ -117,7 +117,7 @@ const MessageInput = ({
|
|||||||
file,
|
file,
|
||||||
}) => {
|
}) => {
|
||||||
let nextConversationId: string = conversationId;
|
let nextConversationId: string = conversationId;
|
||||||
if (createConversationBeforeUploadDocument && !conversationId) {
|
if (createConversationBeforeUploadDocument) {
|
||||||
const creatingRet = await createConversationBeforeUploadDocument(
|
const creatingRet = await createConversationBeforeUploadDocument(
|
||||||
file.name,
|
file.name,
|
||||||
);
|
);
|
||||||
@ -234,8 +234,14 @@ const MessageInput = ({
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
type={'text'}
|
type={'text'}
|
||||||
|
disabled={disabled}
|
||||||
icon={
|
icon={
|
||||||
<SvgIcon name="paper-clip" width={18} height={22}></SvgIcon>
|
<SvgIcon
|
||||||
|
name="paper-clip"
|
||||||
|
width={18}
|
||||||
|
height={22}
|
||||||
|
disabled={disabled}
|
||||||
|
></SvgIcon>
|
||||||
}
|
}
|
||||||
></Button>
|
></Button>
|
||||||
</Upload>
|
</Upload>
|
||||||
|
@ -2,11 +2,10 @@ import { useDeleteMessage, useFeedback } from '@/hooks/chat-hooks';
|
|||||||
import { useSetModalState } from '@/hooks/common-hooks';
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
import { IRemoveMessageById, useSpeechWithSse } from '@/hooks/logic-hooks';
|
import { IRemoveMessageById, useSpeechWithSse } from '@/hooks/logic-hooks';
|
||||||
import { IFeedbackRequestBody } from '@/interfaces/request/chat';
|
import { IFeedbackRequestBody } from '@/interfaces/request/chat';
|
||||||
import { ConversationContext } from '@/pages/chat/context';
|
|
||||||
import { getMessagePureId } from '@/utils/chat';
|
import { getMessagePureId } from '@/utils/chat';
|
||||||
import { hexStringToUint8Array } from '@/utils/common-util';
|
import { hexStringToUint8Array } from '@/utils/common-util';
|
||||||
import { SpeechPlayer } from 'openai-speech-stream-player';
|
import { SpeechPlayer } from 'openai-speech-stream-player';
|
||||||
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
export const useSendFeedback = (messageId: string) => {
|
export const useSendFeedback = (messageId: string) => {
|
||||||
const { visible, hideModal, showModal } = useSetModalState();
|
const { visible, hideModal, showModal } = useSetModalState();
|
||||||
@ -59,24 +58,21 @@ export const useSpeech = (content: string, audioBinary?: string) => {
|
|||||||
const { read } = useSpeechWithSse();
|
const { read } = useSpeechWithSse();
|
||||||
const player = useRef<SpeechPlayer>();
|
const player = useRef<SpeechPlayer>();
|
||||||
const [isPlaying, setIsPlaying] = useState<boolean>(false);
|
const [isPlaying, setIsPlaying] = useState<boolean>(false);
|
||||||
const callback = useContext(ConversationContext);
|
|
||||||
|
|
||||||
const initialize = useCallback(async () => {
|
const initialize = useCallback(async () => {
|
||||||
player.current = new SpeechPlayer({
|
player.current = new SpeechPlayer({
|
||||||
audio: ref.current!,
|
audio: ref.current!,
|
||||||
onPlaying: () => {
|
onPlaying: () => {
|
||||||
setIsPlaying(true);
|
setIsPlaying(true);
|
||||||
callback?.(true);
|
|
||||||
},
|
},
|
||||||
onPause: () => {
|
onPause: () => {
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
callback?.(false);
|
|
||||||
},
|
},
|
||||||
onChunkEnd: () => {},
|
onChunkEnd: () => {},
|
||||||
mimeType: 'audio/mpeg',
|
mimeType: 'audio/mpeg',
|
||||||
});
|
});
|
||||||
await player.current.init();
|
await player.current.init();
|
||||||
}, [callback]);
|
}, []);
|
||||||
|
|
||||||
const pause = useCallback(() => {
|
const pause = useCallback(() => {
|
||||||
player.current?.pause();
|
player.current?.pause();
|
||||||
@ -103,7 +99,11 @@ export const useSpeech = (content: string, audioBinary?: string) => {
|
|||||||
if (audioBinary) {
|
if (audioBinary) {
|
||||||
const units = hexStringToUint8Array(audioBinary);
|
const units = hexStringToUint8Array(audioBinary);
|
||||||
if (units) {
|
if (units) {
|
||||||
player.current?.feed(units);
|
try {
|
||||||
|
player.current?.feed(units);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [audioBinary]);
|
}, [audioBinary]);
|
||||||
|
@ -19,6 +19,7 @@ export enum SharedFrom {
|
|||||||
export enum ChatSearchParams {
|
export enum ChatSearchParams {
|
||||||
DialogId = 'dialogId',
|
DialogId = 'dialogId',
|
||||||
ConversationId = 'conversationId',
|
ConversationId = 'conversationId',
|
||||||
|
isNew = 'isNew',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EmptyConversationId = 'empty';
|
export const EmptyConversationId = 'empty';
|
||||||
|
@ -12,18 +12,22 @@ import {
|
|||||||
import i18n from '@/locales/config';
|
import i18n from '@/locales/config';
|
||||||
import { IClientConversation } from '@/pages/chat/interface';
|
import { IClientConversation } from '@/pages/chat/interface';
|
||||||
import chatService from '@/services/chat-service';
|
import chatService from '@/services/chat-service';
|
||||||
import { buildMessageListWithUuid, isConversationIdExist } from '@/utils/chat';
|
import {
|
||||||
|
buildMessageListWithUuid,
|
||||||
|
getConversationId,
|
||||||
|
isConversationIdExist,
|
||||||
|
} from '@/utils/chat';
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
import { has, set } from 'lodash';
|
import { has, set } from 'lodash';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { useSearchParams } from 'umi';
|
import { history, useSearchParams } from 'umi';
|
||||||
|
|
||||||
//#region logic
|
//#region logic
|
||||||
|
|
||||||
export const useClickDialogCard = () => {
|
export const useClickDialogCard = () => {
|
||||||
const [, setSearchParams] = useSearchParams();
|
const [_, setSearchParams] = useSearchParams();
|
||||||
|
|
||||||
const newQueryParameters: URLSearchParams = useMemo(() => {
|
const newQueryParameters: URLSearchParams = useMemo(() => {
|
||||||
return new URLSearchParams();
|
return new URLSearchParams();
|
||||||
@ -44,6 +48,25 @@ export const useClickDialogCard = () => {
|
|||||||
return { handleClickDialog };
|
return { handleClickDialog };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useClickConversationCard = () => {
|
||||||
|
const [currentQueryParameters, setSearchParams] = useSearchParams();
|
||||||
|
const newQueryParameters: URLSearchParams = useMemo(
|
||||||
|
() => new URLSearchParams(currentQueryParameters.toString()),
|
||||||
|
[currentQueryParameters],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleClickConversation = useCallback(
|
||||||
|
(conversationId: string, isNew: string) => {
|
||||||
|
newQueryParameters.set(ChatSearchParams.ConversationId, conversationId);
|
||||||
|
newQueryParameters.set(ChatSearchParams.isNew, isNew);
|
||||||
|
setSearchParams(newQueryParameters);
|
||||||
|
},
|
||||||
|
[setSearchParams, newQueryParameters],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { handleClickConversation };
|
||||||
|
};
|
||||||
|
|
||||||
export const useGetChatSearchParams = () => {
|
export const useGetChatSearchParams = () => {
|
||||||
const [currentQueryParameters] = useSearchParams();
|
const [currentQueryParameters] = useSearchParams();
|
||||||
|
|
||||||
@ -51,6 +74,7 @@ export const useGetChatSearchParams = () => {
|
|||||||
dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '',
|
dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '',
|
||||||
conversationId:
|
conversationId:
|
||||||
currentQueryParameters.get(ChatSearchParams.ConversationId) || '',
|
currentQueryParameters.get(ChatSearchParams.ConversationId) || '',
|
||||||
|
isNew: currentQueryParameters.get(ChatSearchParams.isNew) || '',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -60,6 +84,7 @@ export const useGetChatSearchParams = () => {
|
|||||||
|
|
||||||
export const useFetchNextDialogList = () => {
|
export const useFetchNextDialogList = () => {
|
||||||
const { handleClickDialog } = useClickDialogCard();
|
const { handleClickDialog } = useClickDialogCard();
|
||||||
|
const { dialogId } = useGetChatSearchParams();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
@ -70,11 +95,20 @@ export const useFetchNextDialogList = () => {
|
|||||||
initialData: [],
|
initialData: [],
|
||||||
gcTime: 0,
|
gcTime: 0,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
queryFn: async () => {
|
refetchOnMount: false,
|
||||||
|
queryFn: async (...params) => {
|
||||||
|
console.log('🚀 ~ queryFn: ~ params:', params);
|
||||||
const { data } = await chatService.listDialog();
|
const { data } = await chatService.listDialog();
|
||||||
|
|
||||||
if (data.retcode === 0 && data.data.length > 0) {
|
if (data.retcode === 0) {
|
||||||
handleClickDialog(data.data[0].id);
|
const list: IDialog[] = data.data;
|
||||||
|
if (list.length > 0) {
|
||||||
|
if (list.every((x) => x.id !== dialogId)) {
|
||||||
|
handleClickDialog(data.data[0].id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
history.push('/chat');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return data?.data ?? [];
|
return data?.data ?? [];
|
||||||
@ -86,6 +120,7 @@ export const useFetchNextDialogList = () => {
|
|||||||
|
|
||||||
export const useSetNextDialog = () => {
|
export const useSetNextDialog = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
isPending: loading,
|
isPending: loading,
|
||||||
@ -96,8 +131,10 @@ export const useSetNextDialog = () => {
|
|||||||
const { data } = await chatService.setDialog(params);
|
const { data } = await chatService.setDialog(params);
|
||||||
if (data.retcode === 0) {
|
if (data.retcode === 0) {
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
|
exact: false,
|
||||||
queryKey: ['fetchDialogList'],
|
queryKey: ['fetchDialogList'],
|
||||||
});
|
});
|
||||||
|
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: ['fetchDialog'],
|
queryKey: ['fetchDialog'],
|
||||||
});
|
});
|
||||||
@ -166,6 +203,7 @@ export const useRemoveNextDialog = () => {
|
|||||||
const { data } = await chatService.removeDialog({ dialogIds });
|
const { data } = await chatService.removeDialog({ dialogIds });
|
||||||
if (data.retcode === 0) {
|
if (data.retcode === 0) {
|
||||||
queryClient.invalidateQueries({ queryKey: ['fetchDialogList'] });
|
queryClient.invalidateQueries({ queryKey: ['fetchDialogList'] });
|
||||||
|
|
||||||
message.success(i18n.t('message.deleted'));
|
message.success(i18n.t('message.deleted'));
|
||||||
}
|
}
|
||||||
return data.retcode;
|
return data.retcode;
|
||||||
@ -181,6 +219,7 @@ export const useRemoveNextDialog = () => {
|
|||||||
|
|
||||||
export const useFetchNextConversationList = () => {
|
export const useFetchNextConversationList = () => {
|
||||||
const { dialogId } = useGetChatSearchParams();
|
const { dialogId } = useGetChatSearchParams();
|
||||||
|
const { handleClickConversation } = useClickConversationCard();
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
isFetching: loading,
|
isFetching: loading,
|
||||||
@ -193,7 +232,9 @@ export const useFetchNextConversationList = () => {
|
|||||||
enabled: !!dialogId,
|
enabled: !!dialogId,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await chatService.listConversation({ dialogId });
|
const { data } = await chatService.listConversation({ dialogId });
|
||||||
|
if (data.retcode === 0 && data.data.length > 0) {
|
||||||
|
handleClickConversation(data.data[0].id, '');
|
||||||
|
}
|
||||||
return data?.data;
|
return data?.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -202,7 +243,7 @@ export const useFetchNextConversationList = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useFetchNextConversation = () => {
|
export const useFetchNextConversation = () => {
|
||||||
const { conversationId } = useGetChatSearchParams();
|
const { isNew, conversationId } = useGetChatSearchParams();
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
isFetching: loading,
|
isFetching: loading,
|
||||||
@ -214,17 +255,9 @@ export const useFetchNextConversation = () => {
|
|||||||
gcTime: 0,
|
gcTime: 0,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
if (isConversationIdExist(conversationId)) {
|
if (isNew !== 'true' && isConversationIdExist(conversationId)) {
|
||||||
const { data } = await chatService.getConversation({ conversationId });
|
const { data } = await chatService.getConversation({ conversationId });
|
||||||
// if (data.retcode === 0 && needToBeSaved) {
|
|
||||||
// yield put({
|
|
||||||
// type: 'kFModel/fetch_document_thumbnails',
|
|
||||||
// payload: {
|
|
||||||
// doc_ids: getDocumentIdsFromConversionReference(data.data),
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// yield put({ type: 'setCurrentConversation', payload: data.data });
|
|
||||||
// }
|
|
||||||
const conversation = data?.data ?? {};
|
const conversation = data?.data ?? {};
|
||||||
|
|
||||||
const messageList = buildMessageListWithUuid(conversation?.message);
|
const messageList = buildMessageListWithUuid(conversation?.message);
|
||||||
@ -265,7 +298,12 @@ export const useUpdateNextConversation = () => {
|
|||||||
} = useMutation({
|
} = useMutation({
|
||||||
mutationKey: ['updateConversation'],
|
mutationKey: ['updateConversation'],
|
||||||
mutationFn: async (params: Record<string, any>) => {
|
mutationFn: async (params: Record<string, any>) => {
|
||||||
const { data } = await chatService.setConversation(params);
|
const { data } = await chatService.setConversation({
|
||||||
|
...params,
|
||||||
|
conversation_id: params.conversation_id
|
||||||
|
? params.conversation_id
|
||||||
|
: getConversationId(),
|
||||||
|
});
|
||||||
if (data.retcode === 0) {
|
if (data.retcode === 0) {
|
||||||
queryClient.invalidateQueries({ queryKey: ['fetchConversationList'] });
|
queryClient.invalidateQueries({ queryKey: ['fetchConversationList'] });
|
||||||
}
|
}
|
||||||
|
@ -224,6 +224,7 @@ export const useSendMessageWithSse = (
|
|||||||
const send = useCallback(
|
const send = useCallback(
|
||||||
async (
|
async (
|
||||||
body: any,
|
body: any,
|
||||||
|
controller?: AbortController,
|
||||||
): Promise<{ response: Response; data: ResponseType } | undefined> => {
|
): Promise<{ response: Response; data: ResponseType } | undefined> => {
|
||||||
try {
|
try {
|
||||||
setDone(false);
|
setDone(false);
|
||||||
@ -234,6 +235,7 @@ export const useSendMessageWithSse = (
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
|
signal: controller?.signal,
|
||||||
});
|
});
|
||||||
|
|
||||||
const res = response.clone().json();
|
const res = response.clone().json();
|
||||||
@ -249,6 +251,7 @@ export const useSendMessageWithSse = (
|
|||||||
const { done, value } = x;
|
const { done, value } = x;
|
||||||
if (done) {
|
if (done) {
|
||||||
console.info('done');
|
console.info('done');
|
||||||
|
setAnswer({} as IAnswer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -268,9 +271,12 @@ export const useSendMessageWithSse = (
|
|||||||
}
|
}
|
||||||
console.info('done?');
|
console.info('done?');
|
||||||
setDone(true);
|
setDone(true);
|
||||||
|
setAnswer({} as IAnswer);
|
||||||
return { data: await res, response };
|
return { data: await res, response };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setDone(true);
|
setDone(true);
|
||||||
|
setAnswer({} as IAnswer);
|
||||||
|
|
||||||
console.warn(e);
|
console.warn(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -63,6 +63,7 @@ export interface IConversation {
|
|||||||
name: string;
|
name: string;
|
||||||
update_date: string;
|
update_date: string;
|
||||||
update_time: number;
|
update_time: number;
|
||||||
|
is_new: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
|
@ -580,7 +580,7 @@ The above is the content you need to summarize.`,
|
|||||||
addGoogleRegion: 'Google Cloud Region',
|
addGoogleRegion: 'Google Cloud Region',
|
||||||
GoogleRegionMessage: 'Please input Google Cloud Region',
|
GoogleRegionMessage: 'Please input Google Cloud Region',
|
||||||
modelProvidersWarn:
|
modelProvidersWarn:
|
||||||
'Please add both embedding model and LLM in <b>Settings > Model</b> providers firstly.',
|
'Please add both embedding model and LLM in <b>Settings > Model providers</b> firstly.',
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
registered: 'Registered!',
|
registered: 'Registered!',
|
||||||
|
@ -19,10 +19,13 @@ import {
|
|||||||
} from '@/hooks/chat-hooks';
|
} from '@/hooks/chat-hooks';
|
||||||
import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
|
import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { ConversationContext } from '../context';
|
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
const ChatContainer = () => {
|
interface IProps {
|
||||||
|
controller: AbortController;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChatContainer = ({ controller }: IProps) => {
|
||||||
const { conversationId } = useGetChatSearchParams();
|
const { conversationId } = useGetChatSearchParams();
|
||||||
const { data: conversation } = useFetchNextConversation();
|
const { data: conversation } = useFetchNextConversation();
|
||||||
|
|
||||||
@ -36,8 +39,7 @@ const ChatContainer = () => {
|
|||||||
handlePressEnter,
|
handlePressEnter,
|
||||||
regenerateMessage,
|
regenerateMessage,
|
||||||
removeMessageById,
|
removeMessageById,
|
||||||
redirectToNewConversation,
|
} = useSendNextMessage(controller);
|
||||||
} = useSendNextMessage();
|
|
||||||
|
|
||||||
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
|
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
|
||||||
useClickDrawer();
|
useClickDrawer();
|
||||||
@ -54,35 +56,33 @@ const ChatContainer = () => {
|
|||||||
<Flex flex={1} vertical className={styles.messageContainer}>
|
<Flex flex={1} vertical className={styles.messageContainer}>
|
||||||
<div>
|
<div>
|
||||||
<Spin spinning={loading}>
|
<Spin spinning={loading}>
|
||||||
<ConversationContext.Provider value={redirectToNewConversation}>
|
{derivedMessages?.map((message, i) => {
|
||||||
{derivedMessages?.map((message, i) => {
|
return (
|
||||||
return (
|
<MessageItem
|
||||||
<MessageItem
|
loading={
|
||||||
loading={
|
message.role === MessageType.Assistant &&
|
||||||
message.role === MessageType.Assistant &&
|
sendLoading &&
|
||||||
sendLoading &&
|
derivedMessages.length - 1 === i
|
||||||
derivedMessages.length - 1 === i
|
}
|
||||||
}
|
key={message.id}
|
||||||
key={message.id}
|
item={message}
|
||||||
item={message}
|
nickname={userInfo.nickname}
|
||||||
nickname={userInfo.nickname}
|
avatar={userInfo.avatar}
|
||||||
avatar={userInfo.avatar}
|
reference={buildMessageItemReference(
|
||||||
reference={buildMessageItemReference(
|
{
|
||||||
{
|
message: derivedMessages,
|
||||||
message: derivedMessages,
|
reference: conversation.reference,
|
||||||
reference: conversation.reference,
|
},
|
||||||
},
|
message,
|
||||||
message,
|
)}
|
||||||
)}
|
clickDocumentButton={clickDocumentButton}
|
||||||
clickDocumentButton={clickDocumentButton}
|
index={i}
|
||||||
index={i}
|
removeMessageById={removeMessageById}
|
||||||
removeMessageById={removeMessageById}
|
regenerateMessage={regenerateMessage}
|
||||||
regenerateMessage={regenerateMessage}
|
sendLoading={sendLoading}
|
||||||
sendLoading={sendLoading}
|
></MessageItem>
|
||||||
></MessageItem>
|
);
|
||||||
);
|
})}
|
||||||
})}
|
|
||||||
</ConversationContext.Provider>
|
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
<div ref={ref} />
|
<div ref={ref} />
|
||||||
|
@ -1,6 +1 @@
|
|||||||
export enum ChatSearchParams {
|
|
||||||
DialogId = 'dialogId',
|
|
||||||
ConversationId = 'conversationId',
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EmptyConversationId = 'empty';
|
export const EmptyConversationId = 'empty';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { MessageType } from '@/constants/chat';
|
import { ChatSearchParams, MessageType } from '@/constants/chat';
|
||||||
import { fileIconMap } from '@/constants/common';
|
import { fileIconMap } from '@/constants/common';
|
||||||
import {
|
import {
|
||||||
useFetchManualConversation,
|
useFetchManualConversation,
|
||||||
@ -24,6 +24,8 @@ import {
|
|||||||
} from '@/hooks/logic-hooks';
|
} from '@/hooks/logic-hooks';
|
||||||
import { IConversation, IDialog, Message } from '@/interfaces/database/chat';
|
import { IConversation, IDialog, Message } from '@/interfaces/database/chat';
|
||||||
import { getFileExtension } from '@/utils';
|
import { getFileExtension } from '@/utils';
|
||||||
|
import api from '@/utils/api';
|
||||||
|
import { getConversationId } from '@/utils/chat';
|
||||||
import { useMutationState } from '@tanstack/react-query';
|
import { useMutationState } from '@tanstack/react-query';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import trim from 'lodash/trim';
|
import trim from 'lodash/trim';
|
||||||
@ -32,18 +34,57 @@ import {
|
|||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { useSearchParams } from 'umi';
|
import { useSearchParams } from 'umi';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import { ChatSearchParams } from './constants';
|
|
||||||
import {
|
import {
|
||||||
IClientConversation,
|
IClientConversation,
|
||||||
IMessage,
|
IMessage,
|
||||||
VariableTableDataType,
|
VariableTableDataType,
|
||||||
} from './interface';
|
} from './interface';
|
||||||
|
|
||||||
|
export const useSetChatRouteParams = () => {
|
||||||
|
const [currentQueryParameters, setSearchParams] = useSearchParams();
|
||||||
|
const newQueryParameters: URLSearchParams = useMemo(
|
||||||
|
() => new URLSearchParams(currentQueryParameters.toString()),
|
||||||
|
[currentQueryParameters],
|
||||||
|
);
|
||||||
|
|
||||||
|
const setConversationIsNew = useCallback(
|
||||||
|
(value: string) => {
|
||||||
|
newQueryParameters.set(ChatSearchParams.isNew, value);
|
||||||
|
setSearchParams(newQueryParameters);
|
||||||
|
},
|
||||||
|
[newQueryParameters, setSearchParams],
|
||||||
|
);
|
||||||
|
|
||||||
|
const getConversationIsNew = useCallback(() => {
|
||||||
|
return newQueryParameters.get(ChatSearchParams.isNew);
|
||||||
|
}, [newQueryParameters]);
|
||||||
|
|
||||||
|
return { setConversationIsNew, getConversationIsNew };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSetNewConversationRouteParams = () => {
|
||||||
|
const [currentQueryParameters, setSearchParams] = useSearchParams();
|
||||||
|
const newQueryParameters: URLSearchParams = useMemo(
|
||||||
|
() => new URLSearchParams(currentQueryParameters.toString()),
|
||||||
|
[currentQueryParameters],
|
||||||
|
);
|
||||||
|
|
||||||
|
const setNewConversationRouteParams = useCallback(
|
||||||
|
(conversationId: string, isNew: string) => {
|
||||||
|
newQueryParameters.set(ChatSearchParams.ConversationId, conversationId);
|
||||||
|
newQueryParameters.set(ChatSearchParams.isNew, isNew);
|
||||||
|
setSearchParams(newQueryParameters);
|
||||||
|
},
|
||||||
|
[newQueryParameters, setSearchParams],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { setNewConversationRouteParams };
|
||||||
|
};
|
||||||
|
|
||||||
export const useSelectCurrentDialog = () => {
|
export const useSelectCurrentDialog = () => {
|
||||||
const data = useMutationState({
|
const data = useMutationState({
|
||||||
filters: { mutationKey: ['fetchDialog'] },
|
filters: { mutationKey: ['fetchDialog'] },
|
||||||
@ -169,22 +210,26 @@ export const useSelectDerivedConversationList = () => {
|
|||||||
const { data: conversationList, loading } = useFetchNextConversationList();
|
const { data: conversationList, loading } = useFetchNextConversationList();
|
||||||
const { dialogId } = useGetChatSearchParams();
|
const { dialogId } = useGetChatSearchParams();
|
||||||
const prologue = currentDialog?.prompt_config?.prologue ?? '';
|
const prologue = currentDialog?.prompt_config?.prologue ?? '';
|
||||||
|
const { setNewConversationRouteParams } = useSetNewConversationRouteParams();
|
||||||
|
|
||||||
const addTemporaryConversation = useCallback(() => {
|
const addTemporaryConversation = useCallback(() => {
|
||||||
|
const conversationId = getConversationId();
|
||||||
setList((pre) => {
|
setList((pre) => {
|
||||||
if (dialogId) {
|
if (dialogId) {
|
||||||
|
setNewConversationRouteParams(conversationId, 'true');
|
||||||
const nextList = [
|
const nextList = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: conversationId,
|
||||||
name: t('newConversation'),
|
name: t('newConversation'),
|
||||||
dialog_id: dialogId,
|
dialog_id: dialogId,
|
||||||
|
is_new: true,
|
||||||
message: [
|
message: [
|
||||||
{
|
{
|
||||||
content: prologue,
|
content: prologue,
|
||||||
role: MessageType.Assistant,
|
role: MessageType.Assistant,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} as IConversation,
|
} as any,
|
||||||
...conversationList,
|
...conversationList,
|
||||||
];
|
];
|
||||||
return nextList;
|
return nextList;
|
||||||
@ -192,42 +237,32 @@ export const useSelectDerivedConversationList = () => {
|
|||||||
|
|
||||||
return pre;
|
return pre;
|
||||||
});
|
});
|
||||||
}, [conversationList, dialogId, prologue, t]);
|
}, [conversationList, dialogId, prologue, t, setNewConversationRouteParams]);
|
||||||
|
|
||||||
|
// When you first enter the page, select the top conversation card
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
addTemporaryConversation();
|
setList([...conversationList]);
|
||||||
}, [addTemporaryConversation]);
|
}, [conversationList]);
|
||||||
|
|
||||||
return { list, addTemporaryConversation, loading };
|
return { list, addTemporaryConversation, loading };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useClickConversationCard = () => {
|
|
||||||
const [currentQueryParameters, setSearchParams] = useSearchParams();
|
|
||||||
const newQueryParameters: URLSearchParams = useMemo(
|
|
||||||
() => new URLSearchParams(currentQueryParameters.toString()),
|
|
||||||
[currentQueryParameters],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleClickConversation = useCallback(
|
|
||||||
(conversationId: string) => {
|
|
||||||
newQueryParameters.set(ChatSearchParams.ConversationId, conversationId);
|
|
||||||
setSearchParams(newQueryParameters);
|
|
||||||
},
|
|
||||||
[newQueryParameters, setSearchParams],
|
|
||||||
);
|
|
||||||
|
|
||||||
return { handleClickConversation };
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useSetConversation = () => {
|
export const useSetConversation = () => {
|
||||||
const { dialogId } = useGetChatSearchParams();
|
const { dialogId } = useGetChatSearchParams();
|
||||||
const { updateConversation } = useUpdateNextConversation();
|
const { updateConversation } = useUpdateNextConversation();
|
||||||
|
|
||||||
const setConversation = useCallback(
|
const setConversation = useCallback(
|
||||||
(message: string) => {
|
async (
|
||||||
return updateConversation({
|
message: string,
|
||||||
|
isNew: boolean = false,
|
||||||
|
conversationId?: string,
|
||||||
|
) => {
|
||||||
|
const data = await updateConversation({
|
||||||
dialog_id: dialogId,
|
dialog_id: dialogId,
|
||||||
name: message,
|
name: message,
|
||||||
|
is_new: isNew,
|
||||||
|
conversation_id: conversationId,
|
||||||
message: [
|
message: [
|
||||||
{
|
{
|
||||||
role: MessageType.Assistant,
|
role: MessageType.Assistant,
|
||||||
@ -235,6 +270,8 @@ export const useSetConversation = () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
},
|
},
|
||||||
[updateConversation, dialogId],
|
[updateConversation, dialogId],
|
||||||
);
|
);
|
||||||
@ -242,22 +279,6 @@ export const useSetConversation = () => {
|
|||||||
return { setConversation };
|
return { setConversation };
|
||||||
};
|
};
|
||||||
|
|
||||||
// export const useScrollToBottom = (currentConversation: IClientConversation) => {
|
|
||||||
// const ref = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
// const scrollToBottom = useCallback(() => {
|
|
||||||
// if (currentConversation.id) {
|
|
||||||
// ref.current?.scrollIntoView({ behavior: 'instant' });
|
|
||||||
// }
|
|
||||||
// }, [currentConversation]);
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// scrollToBottom();
|
|
||||||
// }, [scrollToBottom]);
|
|
||||||
|
|
||||||
// return ref;
|
|
||||||
// };
|
|
||||||
|
|
||||||
export const useSelectNextMessages = () => {
|
export const useSelectNextMessages = () => {
|
||||||
const {
|
const {
|
||||||
ref,
|
ref,
|
||||||
@ -271,10 +292,10 @@ export const useSelectNextMessages = () => {
|
|||||||
} = useSelectDerivedMessages();
|
} = useSelectDerivedMessages();
|
||||||
const { data: conversation, loading } = useFetchNextConversation();
|
const { data: conversation, loading } = useFetchNextConversation();
|
||||||
const { data: dialog } = useFetchNextDialog();
|
const { data: dialog } = useFetchNextDialog();
|
||||||
const { conversationId, dialogId } = useGetChatSearchParams();
|
const { conversationId, dialogId, isNew } = useGetChatSearchParams();
|
||||||
|
|
||||||
const addPrologue = useCallback(() => {
|
const addPrologue = useCallback(() => {
|
||||||
if (dialogId !== '' && conversationId === '') {
|
if (dialogId !== '' && isNew === 'true') {
|
||||||
const prologue = dialog.prompt_config?.prologue;
|
const prologue = dialog.prompt_config?.prologue;
|
||||||
|
|
||||||
const nextMessage = {
|
const nextMessage = {
|
||||||
@ -285,17 +306,25 @@ export const useSelectNextMessages = () => {
|
|||||||
|
|
||||||
setDerivedMessages([nextMessage]);
|
setDerivedMessages([nextMessage]);
|
||||||
}
|
}
|
||||||
}, [conversationId, dialog, dialogId, setDerivedMessages]);
|
}, [isNew, dialog, dialogId, setDerivedMessages]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
addPrologue();
|
addPrologue();
|
||||||
}, [addPrologue]);
|
}, [addPrologue]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (conversationId) {
|
if (
|
||||||
|
conversationId &&
|
||||||
|
isNew !== 'true' &&
|
||||||
|
conversation.message?.length > 0
|
||||||
|
) {
|
||||||
setDerivedMessages(conversation.message);
|
setDerivedMessages(conversation.message);
|
||||||
}
|
}
|
||||||
}, [conversation.message, conversationId, setDerivedMessages]);
|
|
||||||
|
if (!conversationId) {
|
||||||
|
setDerivedMessages([]);
|
||||||
|
}
|
||||||
|
}, [conversation.message, conversationId, setDerivedMessages, isNew]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ref,
|
ref,
|
||||||
@ -325,12 +354,14 @@ export const useHandleMessageInputChange = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSendNextMessage = () => {
|
export const useSendNextMessage = (controller: AbortController) => {
|
||||||
const { setConversation } = useSetConversation();
|
const { setConversation } = useSetConversation();
|
||||||
const { conversationId } = useGetChatSearchParams();
|
const { conversationId, isNew } = useGetChatSearchParams();
|
||||||
const { handleInputChange, value, setValue } = useHandleMessageInputChange();
|
const { handleInputChange, value, setValue } = useHandleMessageInputChange();
|
||||||
const { handleClickConversation } = useClickConversationCard();
|
|
||||||
const { send, answer, done, setDone, resetAnswer } = useSendMessageWithSse();
|
const { send, answer, done } = useSendMessageWithSse(
|
||||||
|
api.completeConversation,
|
||||||
|
);
|
||||||
const {
|
const {
|
||||||
ref,
|
ref,
|
||||||
derivedMessages,
|
derivedMessages,
|
||||||
@ -341,17 +372,8 @@ export const useSendNextMessage = () => {
|
|||||||
removeMessageById,
|
removeMessageById,
|
||||||
removeMessagesAfterCurrentMessage,
|
removeMessagesAfterCurrentMessage,
|
||||||
} = useSelectNextMessages();
|
} = useSelectNextMessages();
|
||||||
const { data: dialog } = useFetchNextDialog();
|
const { setConversationIsNew, getConversationIsNew } =
|
||||||
const currentConversationIdRef = useRef<string>('');
|
useSetChatRouteParams();
|
||||||
|
|
||||||
const redirectToNewConversation = useCallback(
|
|
||||||
(isPlaying: boolean) => {
|
|
||||||
if (!conversationId && dialog?.prompt_config?.tts && !isPlaying) {
|
|
||||||
handleClickConversation(currentConversationIdRef.current);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[dialog, handleClickConversation, conversationId],
|
|
||||||
);
|
|
||||||
|
|
||||||
const sendMessage = useCallback(
|
const sendMessage = useCallback(
|
||||||
async ({
|
async ({
|
||||||
@ -363,49 +385,46 @@ export const useSendNextMessage = () => {
|
|||||||
currentConversationId?: string;
|
currentConversationId?: string;
|
||||||
messages?: Message[];
|
messages?: Message[];
|
||||||
}) => {
|
}) => {
|
||||||
const res = await send({
|
const res = await send(
|
||||||
conversation_id: currentConversationId ?? conversationId,
|
{
|
||||||
messages: [...(messages ?? derivedMessages ?? []), message],
|
conversation_id: currentConversationId ?? conversationId,
|
||||||
});
|
messages: [...(messages ?? derivedMessages ?? []), message],
|
||||||
|
},
|
||||||
|
controller,
|
||||||
|
);
|
||||||
|
|
||||||
if (res && (res?.response.status !== 200 || res?.data?.retcode !== 0)) {
|
if (res && (res?.response.status !== 200 || res?.data?.retcode !== 0)) {
|
||||||
// cancel loading
|
// cancel loading
|
||||||
setValue(message.content);
|
setValue(message.content);
|
||||||
console.info('removeLatestMessage111');
|
console.info('removeLatestMessage111');
|
||||||
removeLatestMessage();
|
removeLatestMessage();
|
||||||
} else {
|
|
||||||
if (currentConversationId) {
|
|
||||||
console.info('111');
|
|
||||||
// new conversation
|
|
||||||
if (!dialog?.prompt_config?.tts) {
|
|
||||||
handleClickConversation(currentConversationId);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.info('222');
|
|
||||||
// fetchConversation(conversationId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
dialog,
|
|
||||||
derivedMessages,
|
derivedMessages,
|
||||||
conversationId,
|
conversationId,
|
||||||
handleClickConversation,
|
|
||||||
removeLatestMessage,
|
removeLatestMessage,
|
||||||
setValue,
|
setValue,
|
||||||
send,
|
send,
|
||||||
|
controller,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSendMessage = useCallback(
|
const handleSendMessage = useCallback(
|
||||||
async (message: Message) => {
|
async (message: Message) => {
|
||||||
if (conversationId !== '') {
|
const isNew = getConversationIsNew();
|
||||||
|
if (isNew !== 'true') {
|
||||||
sendMessage({ message });
|
sendMessage({ message });
|
||||||
} else {
|
} else {
|
||||||
const data = await setConversation(message.content);
|
const data = await setConversation(
|
||||||
|
message.content,
|
||||||
|
true,
|
||||||
|
conversationId,
|
||||||
|
);
|
||||||
if (data.retcode === 0) {
|
if (data.retcode === 0) {
|
||||||
|
setConversationIsNew('');
|
||||||
const id = data.data.id;
|
const id = data.data.id;
|
||||||
currentConversationIdRef.current = id;
|
// currentConversationIdRef.current = id;
|
||||||
sendMessage({
|
sendMessage({
|
||||||
message,
|
message,
|
||||||
currentConversationId: id,
|
currentConversationId: id,
|
||||||
@ -414,7 +433,13 @@ export const useSendNextMessage = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[conversationId, setConversation, sendMessage],
|
[
|
||||||
|
setConversation,
|
||||||
|
sendMessage,
|
||||||
|
setConversationIsNew,
|
||||||
|
getConversationIsNew,
|
||||||
|
conversationId,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { regenerateMessage } = useRegenerateMessage({
|
const { regenerateMessage } = useRegenerateMessage({
|
||||||
@ -425,24 +450,10 @@ export const useSendNextMessage = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// #1289
|
// #1289
|
||||||
console.log('🚀 ~ useEffect ~ answer:', answer, done);
|
if (answer.answer && conversationId && isNew !== 'true') {
|
||||||
if (
|
|
||||||
answer.answer &&
|
|
||||||
(answer?.conversationId === conversationId ||
|
|
||||||
((!done || (done && answer.audio_binary)) && conversationId === ''))
|
|
||||||
) {
|
|
||||||
addNewestAnswer(answer);
|
addNewestAnswer(answer);
|
||||||
}
|
}
|
||||||
}, [answer, addNewestAnswer, conversationId, done]);
|
}, [answer, addNewestAnswer, conversationId, isNew]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// #1289 switch to another conversion window when the last conversion answer doesn't finish.
|
|
||||||
if (conversationId) {
|
|
||||||
setDone(true);
|
|
||||||
} else {
|
|
||||||
resetAnswer();
|
|
||||||
}
|
|
||||||
}, [setDone, conversationId, resetAnswer]);
|
|
||||||
|
|
||||||
const handlePressEnter = useCallback(
|
const handlePressEnter = useCallback(
|
||||||
(documentIds: string[]) => {
|
(documentIds: string[]) => {
|
||||||
@ -479,7 +490,6 @@ export const useSendNextMessage = () => {
|
|||||||
ref,
|
ref,
|
||||||
derivedMessages,
|
derivedMessages,
|
||||||
removeMessageById,
|
removeMessageById,
|
||||||
redirectToNewConversation,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -494,15 +504,12 @@ export const useGetFileIcon = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useDeleteConversation = () => {
|
export const useDeleteConversation = () => {
|
||||||
const { handleClickConversation } = useClickConversationCard();
|
|
||||||
const showDeleteConfirm = useShowDeleteConfirm();
|
const showDeleteConfirm = useShowDeleteConfirm();
|
||||||
const { removeConversation } = useRemoveNextConversation();
|
const { removeConversation } = useRemoveNextConversation();
|
||||||
|
|
||||||
const deleteConversation = (conversationIds: Array<string>) => async () => {
|
const deleteConversation = (conversationIds: Array<string>) => async () => {
|
||||||
const ret = await removeConversation(conversationIds);
|
const ret = await removeConversation(conversationIds);
|
||||||
if (ret === 0) {
|
|
||||||
handleClickConversation('');
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -531,6 +538,7 @@ export const useRenameConversation = () => {
|
|||||||
...conversation,
|
...conversation,
|
||||||
conversation_id: conversation.id,
|
conversation_id: conversation.id,
|
||||||
name,
|
name,
|
||||||
|
is_new: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ret.retcode === 0) {
|
if (ret.retcode === 0) {
|
||||||
@ -564,7 +572,7 @@ export const useRenameConversation = () => {
|
|||||||
export const useGetSendButtonDisabled = () => {
|
export const useGetSendButtonDisabled = () => {
|
||||||
const { dialogId, conversationId } = useGetChatSearchParams();
|
const { dialogId, conversationId } = useGetChatSearchParams();
|
||||||
|
|
||||||
return dialogId === '' && conversationId === '';
|
return dialogId === '' || conversationId === '';
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSendButtonDisabled = (value: string) => {
|
export const useSendButtonDisabled = (value: string) => {
|
||||||
@ -575,18 +583,13 @@ export const useCreateConversationBeforeUploadDocument = () => {
|
|||||||
const { setConversation } = useSetConversation();
|
const { setConversation } = useSetConversation();
|
||||||
const { dialogId } = useGetChatSearchParams();
|
const { dialogId } = useGetChatSearchParams();
|
||||||
|
|
||||||
const { handleClickConversation } = useClickConversationCard();
|
|
||||||
|
|
||||||
const createConversationBeforeUploadDocument = useCallback(
|
const createConversationBeforeUploadDocument = useCallback(
|
||||||
async (message: string) => {
|
async (message: string) => {
|
||||||
const data = await setConversation(message);
|
const data = await setConversation(message, true);
|
||||||
if (data.retcode === 0) {
|
|
||||||
const id = data.data.id;
|
|
||||||
handleClickConversation(id);
|
|
||||||
}
|
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
[setConversation, handleClickConversation],
|
[setConversation],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -17,15 +17,15 @@ import {
|
|||||||
Space,
|
Space,
|
||||||
Spin,
|
Spin,
|
||||||
Tag,
|
Tag,
|
||||||
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { MenuItemProps } from 'antd/lib/menu/MenuItem';
|
import { MenuItemProps } from 'antd/lib/menu/MenuItem';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import ChatConfigurationModal from './chat-configuration-modal';
|
import ChatConfigurationModal from './chat-configuration-modal';
|
||||||
import ChatContainer from './chat-container';
|
import ChatContainer from './chat-container';
|
||||||
import {
|
import {
|
||||||
useClickConversationCard,
|
|
||||||
useDeleteConversation,
|
useDeleteConversation,
|
||||||
useDeleteDialog,
|
useDeleteDialog,
|
||||||
useEditDialog,
|
useEditDialog,
|
||||||
@ -36,6 +36,7 @@ import {
|
|||||||
|
|
||||||
import ChatOverviewModal from '@/components/api-service/chat-overview-modal';
|
import ChatOverviewModal from '@/components/api-service/chat-overview-modal';
|
||||||
import {
|
import {
|
||||||
|
useClickConversationCard,
|
||||||
useClickDialogCard,
|
useClickDialogCard,
|
||||||
useFetchNextDialogList,
|
useFetchNextDialogList,
|
||||||
useGetChatSearchParams,
|
useGetChatSearchParams,
|
||||||
@ -89,6 +90,7 @@ const Chat = () => {
|
|||||||
showModal: showOverviewModal,
|
showModal: showOverviewModal,
|
||||||
} = useSetModalState();
|
} = useSetModalState();
|
||||||
const { currentRecord, setRecord } = useSetSelectedRecord<IDialog>();
|
const { currentRecord, setRecord } = useSetSelectedRecord<IDialog>();
|
||||||
|
const [controller, setController] = useState(new AbortController());
|
||||||
|
|
||||||
const handleAppCardEnter = (id: string) => () => {
|
const handleAppCardEnter = (id: string) => () => {
|
||||||
handleItemEnter(id);
|
handleItemEnter(id);
|
||||||
@ -139,31 +141,28 @@ const Chat = () => {
|
|||||||
showConversationRenameModal(conversationId);
|
showConversationRenameModal(conversationId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDialogCardClick = (dialogId: string) => () => {
|
const handleDialogCardClick = useCallback(
|
||||||
handleClickDialog(dialogId);
|
(dialogId: string) => () => {
|
||||||
};
|
handleClickDialog(dialogId);
|
||||||
|
},
|
||||||
|
[handleClickDialog],
|
||||||
|
);
|
||||||
|
|
||||||
const handleConversationCardClick = (dialogId: string) => () => {
|
const handleConversationCardClick = useCallback(
|
||||||
handleClickConversation(dialogId);
|
(conversationId: string, isNew: boolean) => () => {
|
||||||
};
|
handleClickConversation(conversationId, isNew ? 'true' : '');
|
||||||
|
setController((pre) => {
|
||||||
|
pre.abort();
|
||||||
|
return new AbortController();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[handleClickConversation],
|
||||||
|
);
|
||||||
|
|
||||||
const handleCreateTemporaryConversation = useCallback(() => {
|
const handleCreateTemporaryConversation = useCallback(() => {
|
||||||
addTemporaryConversation();
|
addTemporaryConversation();
|
||||||
}, [addTemporaryConversation]);
|
}, [addTemporaryConversation]);
|
||||||
|
|
||||||
const items: MenuProps['items'] = [
|
|
||||||
{
|
|
||||||
key: '1',
|
|
||||||
onClick: handleCreateTemporaryConversation,
|
|
||||||
label: (
|
|
||||||
<Space>
|
|
||||||
<PlusOutlined />
|
|
||||||
{t('newChat')}
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const buildAppItems = (dialog: IDialog) => {
|
const buildAppItems = (dialog: IDialog) => {
|
||||||
const dialogId = dialog.id;
|
const dialogId = dialog.id;
|
||||||
|
|
||||||
@ -297,10 +296,9 @@ const Chat = () => {
|
|||||||
<b>{t('chat')}</b>
|
<b>{t('chat')}</b>
|
||||||
<Tag>{conversationList.length}</Tag>
|
<Tag>{conversationList.length}</Tag>
|
||||||
</Space>
|
</Space>
|
||||||
<Dropdown menu={{ items }}>
|
<Tooltip title={t('newChat')}>
|
||||||
{/* <FormOutlined /> */}
|
<PlusOutlined onClick={handleCreateTemporaryConversation} />
|
||||||
<PlusOutlined />
|
</Tooltip>
|
||||||
</Dropdown>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<Divider></Divider>
|
<Divider></Divider>
|
||||||
<Flex vertical gap={10} className={styles.chatTitleContent}>
|
<Flex vertical gap={10} className={styles.chatTitleContent}>
|
||||||
@ -312,7 +310,7 @@ const Chat = () => {
|
|||||||
<Card
|
<Card
|
||||||
key={x.id}
|
key={x.id}
|
||||||
hoverable
|
hoverable
|
||||||
onClick={handleConversationCardClick(x.id)}
|
onClick={handleConversationCardClick(x.id, x.is_new)}
|
||||||
onMouseEnter={handleConversationCardEnter(x.id)}
|
onMouseEnter={handleConversationCardEnter(x.id)}
|
||||||
onMouseLeave={handleConversationItemLeave}
|
onMouseLeave={handleConversationItemLeave}
|
||||||
className={classNames(styles.chatTitleCard, {
|
className={classNames(styles.chatTitleCard, {
|
||||||
@ -347,7 +345,7 @@ const Chat = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Divider type={'vertical'} className={styles.divider}></Divider>
|
<Divider type={'vertical'} className={styles.divider}></Divider>
|
||||||
<ChatContainer></ChatContainer>
|
<ChatContainer controller={controller}></ChatContainer>
|
||||||
{dialogEditVisible && (
|
{dialogEditVisible && (
|
||||||
<ChatConfigurationModal
|
<ChatConfigurationModal
|
||||||
visible={dialogEditVisible}
|
visible={dialogEditVisible}
|
||||||
|
@ -89,7 +89,7 @@ const FishAudioModal = ({
|
|||||||
<Form.Item<FieldType>
|
<Form.Item<FieldType>
|
||||||
label={t('addFishAudioRefID')}
|
label={t('addFishAudioRefID')}
|
||||||
name="fish_audio_refid"
|
name="fish_audio_refid"
|
||||||
rules={[{ required: false, message: t('FishAudioRefIDMessage') }]}
|
rules={[{ required: true, message: t('FishAudioRefIDMessage') }]}
|
||||||
>
|
>
|
||||||
<Input placeholder={t('FishAudioRefIDMessage')} />
|
<Input placeholder={t('FishAudioRefIDMessage')} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -32,3 +32,7 @@ export const buildMessageListWithUuid = (messages?: Message[]) => {
|
|||||||
})) ?? []
|
})) ?? []
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getConversationId = () => {
|
||||||
|
return uuid().replace(/-/g, '');
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user