|
@@ -1,89 +1,317 @@
|
|
"use client";
|
|
"use client";
|
|
-import { getApiUrl } from '@/utils/common';
|
|
|
|
-import { getUserSession } from '@/utils/user';
|
|
|
|
|
|
+import { getApiUrl } from "@/utils/common";
|
|
|
|
+import { getUserSession } from "@/utils/user";
|
|
import { useState, useEffect } from "react";
|
|
import { useState, useEffect } from "react";
|
|
-import { useRouter } from "next/navigation";
|
|
|
|
|
|
+import { theme } from "antd";
|
|
|
|
+import { ThemeProvider, css, cx } from "antd-style";
|
|
|
|
+import { useTheme } from "next-themes";
|
|
import { ProChat, ProChatInstance } from "@ant-design/pro-chat";
|
|
import { ProChat, ProChatInstance } from "@ant-design/pro-chat";
|
|
-import { RiAddCircleFill, RiCalendarCloseLine,RiLoader2Fill } from "react-icons/ri";
|
|
|
|
-import Image from "next/image";
|
|
|
|
-import { getChatSession, getChatMessage, chatSubmit } from "@/api/client";
|
|
|
|
-import { ChatSessionResult, ChatMessageResult } from "@/utils/clientsApis";
|
|
|
|
|
|
+import {
|
|
|
|
+ RiAddCircleFill,
|
|
|
|
+ RiCalendarCloseLine,
|
|
|
|
+ RiLoader2Fill,
|
|
|
|
+ RiBookReadLine,
|
|
|
|
+} from "react-icons/ri";
|
|
|
|
+import {
|
|
|
|
+ getChatSession,
|
|
|
|
+ getChatMessage,
|
|
|
|
+ getEmployeeDetail,
|
|
|
|
+} from "@/api/client";
|
|
|
|
+import { ChatSessionResult, EmployeeSearchResult } from "@/utils/clientsApis";
|
|
|
|
|
|
-import { ChatMessage, MessageChange } from "@/utils/chat";
|
|
|
|
|
|
+import {
|
|
|
|
+ LoadLocalChatList,
|
|
|
|
+ ChatMessage,
|
|
|
|
+ MessageChange,
|
|
|
|
+ ChatAiModel,
|
|
|
|
+ SetChatModelListForLocalStorage,
|
|
|
|
+ GetChatModelListForLocalStorage,
|
|
|
|
+ SetChatLastUsedForLocalStorage,
|
|
|
|
+ UpdateLocalChatListForConversationId,
|
|
|
|
+ GetLocalChatModelDetails,
|
|
|
|
+} from "@/utils/chat";
|
|
import { useGlobalContext } from "@/providers/GlobalProvider";
|
|
import { useGlobalContext } from "@/providers/GlobalProvider";
|
|
|
|
|
|
-var msgId = "";
|
|
|
|
-
|
|
|
|
export default function Dialogue() {
|
|
export default function Dialogue() {
|
|
- const router = useRouter();
|
|
|
|
|
|
+ const themeBig = useTheme();
|
|
|
|
+ const {
|
|
|
|
+ changeMenuIndex,
|
|
|
|
+ loginShow,
|
|
|
|
+ changeLoginShow,
|
|
|
|
+ listType,
|
|
|
|
+ changeListType,
|
|
|
|
+ agentId,
|
|
|
|
+ changeAgentId,
|
|
|
|
+ conversationId,
|
|
|
|
+ changeConversationId,
|
|
|
|
+ } = useGlobalContext();
|
|
|
|
+ const [employeeSearch, setEmployeeSearch] = useState<EmployeeSearchResult>();
|
|
|
|
|
|
- const [uiMsgId, setUiMsgId] = useState('');
|
|
|
|
- const { changeMenuIndex,loginShow, changeLoginShow } = useGlobalContext();
|
|
|
|
- const [showComponent, setShowComponent] = useState(false);
|
|
|
|
- const [showLetter, setShowLetter] = useState(true);
|
|
|
|
|
|
+ const [showLeftLetter, setShowLeftLetter] = useState(true);
|
|
|
|
+ const [historyOrChatList, setHistoryOrChatList] = useState<number>(0);
|
|
|
|
|
|
- const [chatSessionList, setChatSessionList] = useState<ChatSessionResult[]>([]);
|
|
|
|
|
|
+ const [showComponent, setShowComponent] = useState(false);
|
|
const [iniChatMessage, setIniChatMessage] = useState<ChatMessage[]>();
|
|
const [iniChatMessage, setIniChatMessage] = useState<ChatMessage[]>();
|
|
|
|
|
|
- const handlShowLetter = () => {
|
|
|
|
- setShowLetter(!showLetter);
|
|
|
|
|
|
+ const [chatAiModelList, setChatAiModelList] = useState<ChatAiModel[]>([]);
|
|
|
|
+ const [chatSessionLastId, setChatSessionLastId] = useState<string>("");
|
|
|
|
+ const [chatSessionList, setChatSessionList] = useState<ChatSessionResult[]>(
|
|
|
|
+ []
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ const handlShowLeftLetter = () => {
|
|
|
|
+ setShowLeftLetter(!showLeftLetter);
|
|
};
|
|
};
|
|
|
|
+
|
|
|
|
+ //对话框加载聊天历史记录
|
|
const chatInit = (id: string) => {
|
|
const chatInit = (id: string) => {
|
|
- getChatMessage({ conversationId: id, firstId: "", limit: 100 }).then(
|
|
|
|
- (data) => {
|
|
|
|
- setIniChatMessage(MessageChange(data.data.data));
|
|
|
|
|
|
+ if (id !== "" && !id.includes("guid_0000_")) {
|
|
|
|
+ getChatMessage({
|
|
|
|
+ conversationId: id,
|
|
|
|
+ firstId: "",
|
|
|
|
+ limit: 100,
|
|
|
|
+ agentId,
|
|
|
|
+ }).then((data) => {
|
|
|
|
+ if (data.data.data) {
|
|
|
|
+ setIniChatMessage(MessageChange(data.data.data));
|
|
|
|
+ }
|
|
setShowComponent(true);
|
|
setShowComponent(true);
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ setShowComponent(true);
|
|
|
|
+ }, 500);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ //历史会话 - 点击
|
|
|
|
+ const changeChatSession = (id: string) => {
|
|
|
|
+ if (conversationId !== id) {
|
|
|
|
+ SetChatLastUsedForLocalStorage({
|
|
|
|
+ listType: 0,
|
|
|
|
+ agentId,
|
|
|
|
+ conversationId: id,
|
|
|
|
+ });
|
|
|
|
+ changeConversationId(id);
|
|
|
|
+ changeListType(0);
|
|
|
|
+ setShowComponent(false);
|
|
|
|
+ if (id == "") {
|
|
|
|
+ setIniChatMessage([]);
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ setShowComponent(true);
|
|
|
|
+ }, 200);
|
|
|
|
+ } else {
|
|
|
|
+ chatInit(id);
|
|
}
|
|
}
|
|
- );
|
|
|
|
|
|
+ }
|
|
};
|
|
};
|
|
-
|
|
|
|
- const changeChat = (id: string) => {
|
|
|
|
- if(msgId !== id){
|
|
|
|
- msgId = id;
|
|
|
|
- setUiMsgId(msgId);
|
|
|
|
|
|
+ //助手列表 - 点击
|
|
|
|
+ const changeChatListForLocal = (id: number) => {
|
|
|
|
+ var model = GetLocalChatModelDetails(id);
|
|
|
|
+ if (model !== null) {
|
|
setShowComponent(false);
|
|
setShowComponent(false);
|
|
- chatInit(msgId);
|
|
|
|
|
|
+ setIniChatMessage([]);
|
|
|
|
+ SetChatLastUsedForLocalStorage({
|
|
|
|
+ listType: 1,
|
|
|
|
+ agentId: id,
|
|
|
|
+ conversationId: model.ConversationId,
|
|
|
|
+ });
|
|
|
|
+ changeConversationId(model.ConversationId);
|
|
|
|
+ changeListType(1);
|
|
|
|
+ changeAgentId(id);
|
|
|
|
+ if (model.ConversationId == "") {
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ setShowComponent(true);
|
|
|
|
+ }, 500);
|
|
|
|
+ } else {
|
|
|
|
+ chatInit(model.ConversationId);
|
|
|
|
+ }
|
|
|
|
+ loadChatSession("");
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ //新对话
|
|
|
|
+ const newChat = () => {
|
|
|
|
+ var newConversationId = "guid_0000_" + new Date().getTime();
|
|
|
|
+ setChatSessionList((chatSessionList) => [
|
|
|
|
+ ...[
|
|
|
|
+ {
|
|
|
|
+ id: newConversationId,
|
|
|
|
+ name: "新对话",
|
|
|
|
+ createdAt: new Date().getTime(),
|
|
|
|
+ inputs: {},
|
|
|
|
+ },
|
|
|
|
+ ],
|
|
|
|
+ ...chatSessionList,
|
|
|
|
+ ]);
|
|
|
|
+
|
|
|
|
+ SetChatLastUsedForLocalStorage({
|
|
|
|
+ listType: 0,
|
|
|
|
+ agentId,
|
|
|
|
+ conversationId: newConversationId,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ setHistoryOrChatList(0);
|
|
|
|
+ changeListType(0);
|
|
|
|
+ changeConversationId(newConversationId);
|
|
|
|
+
|
|
|
|
+ setShowComponent(false);
|
|
|
|
+ setIniChatMessage([]);
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ setShowComponent(true);
|
|
|
|
+ }, 200);
|
|
|
|
+ };
|
|
|
|
+ //设置新会话的ID
|
|
|
|
+ const setConversationId = (id: string) => {
|
|
|
|
+ if (listType === 0) {
|
|
|
|
+ if (conversationId.includes("guid_0000_") || conversationId == "") {
|
|
|
|
+ if (chatSessionList !== null && chatSessionList.length > 0) {
|
|
|
|
+ var index = chatSessionList.findIndex((v) => v.id === conversationId);
|
|
|
|
+ if (index >= 0) {
|
|
|
|
+ chatSessionList[index].id = id;
|
|
|
|
+ } else {
|
|
|
|
+ chatSessionList[0].id = id;
|
|
|
|
+ }
|
|
|
|
+ setChatSessionList(chatSessionList);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+ if (listType === 1) {
|
|
|
|
+ console.log(id);
|
|
|
|
+ var list = UpdateLocalChatListForConversationId(agentId, id);
|
|
|
|
+ setChatAiModelList(list);
|
|
|
|
+ }
|
|
|
|
+ changeConversationId(id);
|
|
|
|
+ SetChatLastUsedForLocalStorage({
|
|
|
|
+ listType: listType,
|
|
|
|
+ agentId,
|
|
|
|
+ conversationId: id,
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ //加载助手对应的历史会话
|
|
|
|
+ const loadChatSession = (last_id: string) => {
|
|
|
|
+ setShowComponent(false);
|
|
|
|
+ getChatSession({ agentId: agentId, last_id: last_id, limit: 100 }).then(
|
|
|
|
+ (data) => {
|
|
|
|
+ if (data.code === 0 && data.data.data !== null) {
|
|
|
|
+ if (last_id == "") {
|
|
|
|
+ setChatSessionList(data.data.data);
|
|
|
|
+ } else {
|
|
|
|
+ setChatSessionList((chatSessionList) => [
|
|
|
|
+ ...data.data.data,
|
|
|
|
+ ...chatSessionList,
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ setChatSessionList([]);
|
|
|
|
+ }
|
|
|
|
+ setShowComponent(true);
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+ };
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
changeMenuIndex(1);
|
|
changeMenuIndex(1);
|
|
|
|
+ if (agentId !== null && agentId > 0) {
|
|
|
|
+ //智能体进入 加载本地记录
|
|
|
|
+ getEmployeeDetail({ id: agentId }).then((res) => {
|
|
|
|
+ setHistoryOrChatList(listType);
|
|
|
|
+ if (res.code == 0 && res.data !== null) {
|
|
|
|
+ setEmployeeSearch(res.data);
|
|
|
|
+ var list = LoadLocalChatList(res.data);
|
|
|
|
+ setChatAiModelList(list);
|
|
|
|
+ chatInit(conversationId);
|
|
|
|
+ } else {
|
|
|
|
+ var list = GetChatModelListForLocalStorage();
|
|
|
|
+ setChatAiModelList(list);
|
|
|
|
+ var model = GetLocalChatModelDetails(agentId);
|
|
|
|
+ if (model === null && list !== null && list.length > 0) {
|
|
|
|
+ changeListType(1);
|
|
|
|
+ changeAgentId(list[0].id);
|
|
|
|
+ changeConversationId(list[0].ConversationId);
|
|
|
|
+ chatInit(list[0].ConversationId);
|
|
|
|
+ } else {
|
|
|
|
+ chatInit(model.ConversationId);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ var list = GetChatModelListForLocalStorage();
|
|
|
|
+ setChatAiModelList(list);
|
|
|
|
+ var model = GetLocalChatModelDetails(agentId);
|
|
|
|
+ if (model === null && list !== null && list.length > 0) {
|
|
|
|
+ changeListType(1);
|
|
|
|
+ changeAgentId(list[0].id);
|
|
|
|
+ changeConversationId(list[0].ConversationId);
|
|
|
|
+ chatInit(list[0].ConversationId);
|
|
|
|
+ } else {
|
|
|
|
+ chatInit(model.ConversationId);
|
|
|
|
+ }
|
|
|
|
+ setHistoryOrChatList(1);
|
|
|
|
+ }
|
|
|
|
+ loadChatSession(chatSessionLastId);
|
|
|
|
+ }, [loginShow, agentId, chatSessionLastId]);
|
|
|
|
|
|
- getChatSession({ last_id: "", limit: 100 }).then((data) => {
|
|
|
|
- setShowComponent(false)
|
|
|
|
- if (data.code === 0 && data.data.data !== null) {
|
|
|
|
- msgId = data.data.data[0].id;
|
|
|
|
- chatInit(msgId);
|
|
|
|
- setUiMsgId(msgId);
|
|
|
|
- setChatSessionList(data.data.data);
|
|
|
|
|
|
+ //样式覆盖
|
|
|
|
+ const BarkCustomClassName = cx(
|
|
|
|
+ css(`
|
|
|
|
+ .ant-pro-chat-list-item-message-content{
|
|
|
|
+ background-color: rgb(7 97 255 / 10%);
|
|
}
|
|
}
|
|
- if(data.code === 3){
|
|
|
|
- setShowComponent(true);
|
|
|
|
|
|
+ .ant-pro-chat-input-area{
|
|
|
|
+ background-image: none;
|
|
|
|
+ background-color: #202329;
|
|
}
|
|
}
|
|
- });
|
|
|
|
- }, [loginShow]);
|
|
|
|
|
|
+ .ant-pro-chat-input-area-text-container .acss-sbge3k{
|
|
|
|
+ color:rgb(2 91 237);
|
|
|
|
+ }
|
|
|
|
+ `)
|
|
|
|
+ );
|
|
|
|
+ const LightCustomClassName = cx(
|
|
|
|
+ css(`
|
|
|
|
+ .ant-pro-chat-list-item-message-content{
|
|
|
|
+ background-color: rgb(221 222 224 / 24%);
|
|
|
|
+ }
|
|
|
|
+ .ant-pro-chat-input-area{
|
|
|
|
+ background-image: none;
|
|
|
|
+ background-color: #f8f9fa;
|
|
|
|
+ }
|
|
|
|
+ .ant-pro-chat-input-area-text-container .acss-sbge3k{
|
|
|
|
+ color:#9ca3af;
|
|
|
|
+ }
|
|
|
|
+ `)
|
|
|
|
+ );
|
|
|
|
+ //TAGS
|
|
|
|
+ const readTags = (value:string) => {
|
|
|
|
+ const items = value.split(',');
|
|
|
|
+ return (
|
|
|
|
+ <ul>
|
|
|
|
+ {items.map((item, index) => (
|
|
|
|
+ <span key={index} className="text-sm py-1 px-2 mx-1 rounded-md bg-[#fdebaf] text-[#bc900c]">
|
|
|
|
+ {item.trim().replace('"', '').replace('"', '')}
|
|
|
|
+ </span>
|
|
|
|
+ ))}
|
|
|
|
+ </ul>
|
|
|
|
+ );
|
|
|
|
+ };
|
|
|
|
|
|
return (
|
|
return (
|
|
<div
|
|
<div
|
|
- className="flex justify-between items-center bg-slate-200 dark:bg-[#000]"
|
|
|
|
|
|
+ className="flex justify-between items-center bg-[slate-200] dark:bg-[#000]"
|
|
style={{ height: "100%" }}
|
|
style={{ height: "100%" }}
|
|
>
|
|
>
|
|
- {showLetter && (
|
|
|
|
|
|
+ {showLeftLetter && (
|
|
<div
|
|
<div
|
|
- className={`bg-[#f8f9fa] dark:bg-[#202123] ${
|
|
|
|
- showLetter ? "p-2" : ""
|
|
|
|
- } border-r-1 border-indigo-100 dark:border-r-0`}
|
|
|
|
|
|
+ className={`bg-[#f8f9fa] dark:bg-[#202123] border-r-1 border-indigo-100 dark:border-blue-950 overflow-auto scroll-smooth shrink-0`}
|
|
style={{
|
|
style={{
|
|
height: "calc(100vh - 5rem)",
|
|
height: "calc(100vh - 5rem)",
|
|
width: "20rem",
|
|
width: "20rem",
|
|
}}
|
|
}}
|
|
>
|
|
>
|
|
<div className="sticky top-0 z-50 dark:shadow-[rgba(255,255,255,.15)] backdrop-blur dark:bg-transparent transition-all">
|
|
<div className="sticky top-0 z-50 dark:shadow-[rgba(255,255,255,.15)] backdrop-blur dark:bg-transparent transition-all">
|
|
- <div className="flex justify-between items-center ">
|
|
|
|
|
|
+ <div className="flex justify-between items-center pt-2 px-2">
|
|
<div>
|
|
<div>
|
|
<button
|
|
<button
|
|
- className="inline-flex py-1 px-1 rounded-lg items-center text-white bg-indigo-500 border-0 focus:outline-none hover:bg-indigo-600"
|
|
|
|
- onClick={() => router.push("/")}
|
|
|
|
|
|
+ className="inline-flex py-1 px-1 rounded-lg items-center text-white global-bg-color"
|
|
|
|
+ onClick={newChat}
|
|
>
|
|
>
|
|
<RiAddCircleFill className="w-6 h-6" />
|
|
<RiAddCircleFill className="w-6 h-6" />
|
|
<span className="ml-1 pr-2 flex items-start flex-col leading-none">
|
|
<span className="ml-1 pr-2 flex items-start flex-col leading-none">
|
|
@@ -92,105 +320,207 @@ export default function Dialogue() {
|
|
</button>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div
|
|
<div
|
|
- className="cursor-pointer text-gray-400"
|
|
|
|
- onClick={handlShowLetter}
|
|
|
|
|
|
+ className="cursor-pointer text-gray-400 hover:text-blue-600"
|
|
|
|
+ onClick={handlShowLeftLetter}
|
|
>
|
|
>
|
|
- <Image
|
|
|
|
- src="/icons/icon-shrink.svg"
|
|
|
|
- alt="收缩"
|
|
|
|
- width={32}
|
|
|
|
- height={32}
|
|
|
|
- />
|
|
|
|
|
|
+ <RiBookReadLine className="text-2xl" />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div className="w-full mt-4">
|
|
|
|
+ <div className="flex mx-auto flex-wrap justify-center border-b-2 border-blue-50 shadow-sm dark:border-blue-950 pb-2">
|
|
|
|
+ <a
|
|
|
|
+ className={`cursor-pointer py-1 px-4 mx-4 rounded-lg ${
|
|
|
|
+ historyOrChatList === 0
|
|
|
|
+ ? "global-txt-color"
|
|
|
|
+ : "dark:text-gray-500"
|
|
|
|
+ }`}
|
|
|
|
+ onClick={() => {
|
|
|
|
+ setHistoryOrChatList(0);
|
|
|
|
+ }}
|
|
|
|
+ >
|
|
|
|
+ 对话历史
|
|
|
|
+ </a>
|
|
|
|
+ <a
|
|
|
|
+ className={`cursor-pointer py-1 px-4 mx-4 rounded-lg ${
|
|
|
|
+ historyOrChatList === 1
|
|
|
|
+ ? "global-txt-color"
|
|
|
|
+ : "dark:text-gray-500"
|
|
|
|
+ }`}
|
|
|
|
+ onClick={() => {
|
|
|
|
+ setHistoryOrChatList(1);
|
|
|
|
+ }}
|
|
|
|
+ >
|
|
|
|
+ 助手列表
|
|
|
|
+ </a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
- {chatSessionList !== null && chatSessionList.length > 0 && (
|
|
|
|
- <div className="pt-4">
|
|
|
|
- <div className="mx-auto flex flex-col">
|
|
|
|
- {chatSessionList.map((item) => (
|
|
|
|
- <div className="w-full mt-3 cursor-pointer" key={item.id} onClick={() => changeChat(item.id)}>
|
|
|
|
- <div className={`flex rounded-lg border ${uiMsgId==item.id?'bg-red-100 border-red-100 text-red-500':'border-gray-200 dark:border-gray-700 text-gray-600 dark:text-gray-400 '} p-3 sm:flex-row flex-col`}>
|
|
|
|
- <div className="flex-grow text-ellipsis line-clamp-2">
|
|
|
|
- {item.name}
|
|
|
|
|
|
+
|
|
|
|
+ {historyOrChatList === 0 &&
|
|
|
|
+ chatSessionList !== null &&
|
|
|
|
+ chatSessionList.length > 0 && (
|
|
|
|
+ <div className="py-4 px-2">
|
|
|
|
+ <div className="mx-auto flex flex-col">
|
|
|
|
+ {chatSessionList.map((item) => (
|
|
|
|
+ <div
|
|
|
|
+ className="w-full mt-3 cursor-pointer"
|
|
|
|
+ key={item.id}
|
|
|
|
+ onClick={() => changeChatSession(item.id)}
|
|
|
|
+ >
|
|
|
|
+ <div
|
|
|
|
+ className={`flex rounded border ${
|
|
|
|
+ conversationId == item.id &&
|
|
|
|
+ listType === historyOrChatList
|
|
|
|
+ ? "dark:border-[#0061ff] bg-blue-50 dark:bg-gray-800 text-[#0061ff]"
|
|
|
|
+ : "border-gray-200 dark:border-gray-700 text-gray-600 dark:text-gray-400"
|
|
|
|
+ } p-3 sm:flex-row flex-col`}
|
|
|
|
+ >
|
|
|
|
+ <div className="flex-grow text-ellipsis line-clamp-2">
|
|
|
|
+ <h2 className="pb-2">{item.name}</h2>
|
|
|
|
+ <p className="text-sm text-gray-400">
|
|
|
|
+ {new Date(item.createdAt).toLocaleString()}
|
|
|
|
+ </p>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
- </div>
|
|
|
|
- ))}
|
|
|
|
|
|
+ ))}
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
- </div>
|
|
|
|
- )}
|
|
|
|
- {chatSessionList === null ||
|
|
|
|
- (chatSessionList.length == 0 && (
|
|
|
|
- <div className="w-full px-5 text-gray-200 flex flex-col mt-20">
|
|
|
|
|
|
+ )}
|
|
|
|
+ {historyOrChatList === 0 &&
|
|
|
|
+ (chatSessionList === null || chatSessionList.length == 0) && (
|
|
|
|
+ <div className="w-full px-5 text-gray-200 dark:text-gray-600 flex flex-col mt-20">
|
|
|
|
+ <div className="flex justify-center">
|
|
|
|
+ <RiCalendarCloseLine className="w-16 h-16 text-center" />
|
|
|
|
+ </div>
|
|
|
|
+ <div className="text-center mt-4">对话历史空空如也</div>
|
|
|
|
+ </div>
|
|
|
|
+ )}
|
|
|
|
+
|
|
|
|
+ {historyOrChatList === 1 &&
|
|
|
|
+ chatAiModelList !== null &&
|
|
|
|
+ chatAiModelList.length > 0 && (
|
|
|
|
+ <div className="py-4 px-2">
|
|
|
|
+ <div className="mx-auto flex flex-col">
|
|
|
|
+ {chatAiModelList.map((item) => (
|
|
|
|
+ <div
|
|
|
|
+ className="w-full mt-3 cursor-pointer"
|
|
|
|
+ key={item.id}
|
|
|
|
+ onClick={() => changeChatListForLocal(item.id)}
|
|
|
|
+ >
|
|
|
|
+ <div
|
|
|
|
+ className={`flex rounded border ${
|
|
|
|
+ agentId == item.id && listType === historyOrChatList
|
|
|
|
+ ? "dark:border-[#0061ff] bg-blue-50 dark:bg-gray-800 text-[#0061ff]"
|
|
|
|
+ : "border-gray-200 dark:border-gray-700 text-gray-600 dark:text-gray-400"
|
|
|
|
+ } p-3 sm:flex-row flex-col`}
|
|
|
|
+ >
|
|
|
|
+ <div className="flex flex-row">
|
|
|
|
+ <div className="shrink-0 inline-flex items-center justify-center h-16 overflow-hidden">
|
|
|
|
+ <img src={item.avatar} className="h-16" />
|
|
|
|
+ </div>
|
|
|
|
+ <div className="flex-grow pl-2 pt-2">
|
|
|
|
+ <h2 className="text-base mb-1 line-clamp-1 text-ellipsis">
|
|
|
|
+ {item.name}
|
|
|
|
+ </h2>
|
|
|
|
+ <p className="text-sm line-clamp-1 text-ellipsis">
|
|
|
|
+ {item.estimate}
|
|
|
|
+ </p>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ ))}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ )}
|
|
|
|
+ {historyOrChatList === 1 &&
|
|
|
|
+ (chatAiModelList === null || chatAiModelList.length == 0) && (
|
|
|
|
+ <div className="w-full px-5 text-gray-200 dark:text-gray-600 flex flex-col mt-20">
|
|
<div className="flex justify-center">
|
|
<div className="flex justify-center">
|
|
<RiCalendarCloseLine className="w-16 h-16 text-center" />
|
|
<RiCalendarCloseLine className="w-16 h-16 text-center" />
|
|
</div>
|
|
</div>
|
|
- <div className="text-center mt-4">当前会话列表空空如也</div>
|
|
|
|
|
|
+ <div className="text-center mt-4">当前助手空空如也</div>
|
|
</div>
|
|
</div>
|
|
- ))}
|
|
|
|
|
|
+ )}
|
|
</div>
|
|
</div>
|
|
)}
|
|
)}
|
|
|
|
|
|
- <div
|
|
|
|
- className="bg-[#fcfdff] dark:bg-[#1e1e1e]"
|
|
|
|
- style={{
|
|
|
|
- height: "calc(100vh - 5rem)",
|
|
|
|
- width: showLetter ? "calc(100% - 20rem)" : "100%",
|
|
|
|
|
|
+ <ThemeProvider
|
|
|
|
+ appearance={themeBig.theme}
|
|
|
|
+ theme={{
|
|
|
|
+ algorithm:
|
|
|
|
+ themeBig.theme == "dark"
|
|
|
|
+ ? theme.darkAlgorithm
|
|
|
|
+ : theme.defaultAlgorithm,
|
|
}}
|
|
}}
|
|
>
|
|
>
|
|
- {showComponent && (
|
|
|
|
- <ProChat
|
|
|
|
- style={{
|
|
|
|
- height: "100%",
|
|
|
|
- width: "100%",
|
|
|
|
- }}
|
|
|
|
- initialChats={iniChatMessage}
|
|
|
|
- actions={{
|
|
|
|
- render: (defaultDoms) => {
|
|
|
|
- if (showLetter) {
|
|
|
|
- return defaultDoms;
|
|
|
|
- }
|
|
|
|
- return [
|
|
|
|
- <a
|
|
|
|
- key="handlShowLetter"
|
|
|
|
- className="text-gray-400"
|
|
|
|
- onClick={handlShowLetter}
|
|
|
|
- >
|
|
|
|
- <Image
|
|
|
|
- src="/icons/icon-shrink.svg"
|
|
|
|
- alt="收缩"
|
|
|
|
- width={32}
|
|
|
|
- height={32}
|
|
|
|
- />
|
|
|
|
- </a>,
|
|
|
|
- ...defaultDoms,
|
|
|
|
- ];
|
|
|
|
- },
|
|
|
|
- flexConfig: {
|
|
|
|
- gap: 24,
|
|
|
|
- direction: "horizontal",
|
|
|
|
- justify: "space-start",
|
|
|
|
- },
|
|
|
|
- }}
|
|
|
|
- request={async (messages) => {
|
|
|
|
- const response = await fetch( getApiUrl() +"/gpts/chat/submit", {
|
|
|
|
- method: "POST",
|
|
|
|
- headers: {
|
|
|
|
- "Content-Type": "application/json;charset=UTF-8",
|
|
|
|
- "Authorization": `Bearer ${getUserSession()}`
|
|
|
|
|
|
+ <div
|
|
|
|
+ className={`bg-[#fcfdff] dark:bg-[#202123] grow`}
|
|
|
|
+ style={{
|
|
|
|
+ height: "calc(100vh - 5rem)",
|
|
|
|
+ }}
|
|
|
|
+ >
|
|
|
|
+ {showComponent && (
|
|
|
|
+ <ProChat
|
|
|
|
+ className={
|
|
|
|
+ themeBig.theme == "dark"
|
|
|
|
+ ? BarkCustomClassName
|
|
|
|
+ : LightCustomClassName
|
|
|
|
+ }
|
|
|
|
+ style={{
|
|
|
|
+ height: "100%",
|
|
|
|
+ width: "100%",
|
|
|
|
+ }}
|
|
|
|
+ initialChats={iniChatMessage}
|
|
|
|
+ //helloMessage ={helloMessage}
|
|
|
|
+ actions={{
|
|
|
|
+ render: (defaultDoms) => {
|
|
|
|
+ if (showLeftLetter) {
|
|
|
|
+ return defaultDoms;
|
|
|
|
+ }
|
|
|
|
+ return [
|
|
|
|
+ <a
|
|
|
|
+ key="handlShowLeftLetter"
|
|
|
|
+ className="text-gray-400 hover:text-blue-600"
|
|
|
|
+ onClick={handlShowLeftLetter}
|
|
|
|
+ >
|
|
|
|
+ <RiBookReadLine className="text-2xl" />
|
|
|
|
+ </a>,
|
|
|
|
+ ...defaultDoms,
|
|
|
|
+ ];
|
|
},
|
|
},
|
|
- body: JSON.stringify({
|
|
|
|
- content: messages[messages.length - 1].content,
|
|
|
|
- conversationId: msgId,
|
|
|
|
- }),
|
|
|
|
- });
|
|
|
|
- if (!response.ok || !response.body) {
|
|
|
|
- const errorResponseOptions = {
|
|
|
|
- status: 500,
|
|
|
|
- statusText: "网络错误,请重试!",
|
|
|
|
- };
|
|
|
|
- return new Response(null, errorResponseOptions);
|
|
|
|
- } else {
|
|
|
|
|
|
+ flexConfig: {
|
|
|
|
+ gap: 24,
|
|
|
|
+ direction: "horizontal",
|
|
|
|
+ justify: "space-start",
|
|
|
|
+ },
|
|
|
|
+ }}
|
|
|
|
+ request={async (messages) => {
|
|
|
|
+ const response = await fetch(
|
|
|
|
+ getApiUrl() + "/gpts/chat/submit",
|
|
|
|
+ {
|
|
|
|
+ method: "POST",
|
|
|
|
+ headers: {
|
|
|
|
+ "Content-Type": "application/json;charset=UTF-8",
|
|
|
|
+ Authorization: `Bearer ${getUserSession()}`,
|
|
|
|
+ },
|
|
|
|
+ body: JSON.stringify({
|
|
|
|
+ content: messages[messages.length - 1].content,
|
|
|
|
+ conversationId: conversationId.includes("guid_0000_")
|
|
|
|
+ ? ""
|
|
|
|
+ : conversationId,
|
|
|
|
+ agentId: agentId,
|
|
|
|
+ }),
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+ if (!response.ok || !response.body) {
|
|
|
|
+ const errorResponseOptions = {
|
|
|
|
+ status: 500,
|
|
|
|
+ statusText: "网络错误,请重试!",
|
|
|
|
+ };
|
|
|
|
+ return new Response(null, errorResponseOptions);
|
|
|
|
+ } else {
|
|
const reader = response.body.getReader();
|
|
const reader = response.body.getReader();
|
|
const decoder = new TextDecoder("utf-8");
|
|
const decoder = new TextDecoder("utf-8");
|
|
const encoder = new TextEncoder();
|
|
const encoder = new TextEncoder();
|
|
@@ -209,26 +539,29 @@ export default function Dialogue() {
|
|
stream: true,
|
|
stream: true,
|
|
});
|
|
});
|
|
|
|
|
|
- var linesArray = chunk.split('\n');
|
|
|
|
|
|
+ var linesArray = chunk.split("\n");
|
|
for (var i = 0; i < linesArray.length - 1; i++) {
|
|
for (var i = 0; i < linesArray.length - 1; i++) {
|
|
const line = linesArray[i];
|
|
const line = linesArray[i];
|
|
const message = line.replace("data: ", "");
|
|
const message = line.replace("data: ", "");
|
|
const parsed = JSON.parse(message);
|
|
const parsed = JSON.parse(message);
|
|
- if(!parsed.finish && parsed.answer){
|
|
|
|
|
|
+ if (!parsed.finish && parsed.answer) {
|
|
controller.enqueue(
|
|
controller.enqueue(
|
|
encoder.encode(parsed.answer)
|
|
encoder.encode(parsed.answer)
|
|
);
|
|
);
|
|
- }
|
|
|
|
- else{
|
|
|
|
- if(parsed.need_login){
|
|
|
|
|
|
+ } else {
|
|
|
|
+ if (parsed.finish) {
|
|
|
|
+ setConversationId(parsed.conversation_id);
|
|
|
|
+ }
|
|
|
|
+ if (parsed.need_login) {
|
|
changeLoginShow(true);
|
|
changeLoginShow(true);
|
|
controller.enqueue(
|
|
controller.enqueue(
|
|
- encoder.encode('请登录后使用')
|
|
|
|
|
|
+ encoder.encode("请登录后使用")
|
|
);
|
|
);
|
|
- }
|
|
|
|
- else if(parsed.need_pay){
|
|
|
|
|
|
+ } else if (parsed.need_pay) {
|
|
controller.enqueue(
|
|
controller.enqueue(
|
|
- encoder.encode('当前智能体需要会员才能使用,去开通:[会员套餐](/vip)')
|
|
|
|
|
|
+ encoder.encode(
|
|
|
|
+ "当前智能体需要会员才能使用,去开通:[会员套餐](/vip)"
|
|
|
|
+ )
|
|
);
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -244,21 +577,93 @@ export default function Dialogue() {
|
|
},
|
|
},
|
|
});
|
|
});
|
|
return new Response(readableStream);
|
|
return new Response(readableStream);
|
|
- }
|
|
|
|
- }}
|
|
|
|
- />
|
|
|
|
- )}
|
|
|
|
- {
|
|
|
|
- !showComponent && (
|
|
|
|
|
|
+ }
|
|
|
|
+ }}
|
|
|
|
+ />
|
|
|
|
+ )}
|
|
|
|
+ {!showComponent && (
|
|
<div className="w-full px-5 text-gray-300 flex flex-col mt-40">
|
|
<div className="w-full px-5 text-gray-300 flex flex-col mt-40">
|
|
<div className="flex justify-center">
|
|
<div className="flex justify-center">
|
|
- <RiLoader2Fill className="animate-spin h-16 w-16" />
|
|
|
|
|
|
+ <RiLoader2Fill className="animate-spin h-16 w-16" />
|
|
</div>
|
|
</div>
|
|
<div className="text-center mt-4">会话加载中</div>
|
|
<div className="text-center mt-4">会话加载中</div>
|
|
</div>
|
|
</div>
|
|
- )
|
|
|
|
- }
|
|
|
|
- </div>
|
|
|
|
|
|
+ )}
|
|
|
|
+ </div>
|
|
|
|
+ </ThemeProvider>
|
|
|
|
+
|
|
|
|
+ {employeeSearch != null && (
|
|
|
|
+ <div
|
|
|
|
+ className={`bg-[#ecf1f9] dark:bg-[#202123] border-l-1 border-indigo-100 dark:border-blue-950 overflow-auto scroll-smooth shrink-0`}
|
|
|
|
+ style={{
|
|
|
|
+ height: "calc(100vh - 5rem)",
|
|
|
|
+ width: "25rem",
|
|
|
|
+ }}
|
|
|
|
+ >
|
|
|
|
+ <div className="">
|
|
|
|
+ <div className="h-96 w-11/12 mx-auto relative">
|
|
|
|
+ <div className="h-72 w-10/12 mx-auto absolute rounded-lg bg-[#f6f9fd] top-20 left-0 right-0 shadow-md dark:bg-gray-950"></div>
|
|
|
|
+ <div className="h-64 w-full absolute rounded-lg bg-[#fff] top-28 text-center shadow-lg dark:bg-gray-900">
|
|
|
|
+ <div className="mt-16 text-xl p-3 h-12 overflow-hidden dark:text-gray-500">
|
|
|
|
+ {employeeSearch.title}
|
|
|
|
+ </div>
|
|
|
|
+ <div className="p-3 h-12 overflow-hidden">
|
|
|
|
+ {readTags(employeeSearch.tags)}
|
|
|
|
+ </div>
|
|
|
|
+ <div className="p-5 text-sm text-gray-500">
|
|
|
|
+ <div className="grid grid-cols-3 gap-4">
|
|
|
|
+ <div className="text-center">
|
|
|
|
+ <p className="dark:text-gray-700">被雇佣</p>
|
|
|
|
+ <p className="text-2xl text-gray-700 dark:text-gray-500">{employeeSearch.hireCount}</p>
|
|
|
|
+ </div>
|
|
|
|
+ <div className="text-center">
|
|
|
|
+ <p className="dark:text-gray-700">已服务</p>
|
|
|
|
+ <p className="text-2xl text-gray-700 dark:text-gray-500">{employeeSearch.serviceCount}</p>
|
|
|
|
+ </div>
|
|
|
|
+ <div className="text-center">
|
|
|
|
+ <p className="dark:text-gray-700">业绩单</p>
|
|
|
|
+ <p className="text-2xl text-gray-700 dark:text-gray-500">{employeeSearch.achievementCount}w</p>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div className="h-32 w-32 absolute rounded-full bg-[#fff] top-10 left-0 right-0 mx-auto overflow-hidden">
|
|
|
|
+ <img
|
|
|
|
+ className="object-top"
|
|
|
|
+ src={employeeSearch.avatar}
|
|
|
|
+ ></img>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div className="w-11/12 mx-auto rounded-lg bg-[#fff] dark:bg-gray-900 shadow-md mt-4">
|
|
|
|
+ <div className="p-3">
|
|
|
|
+ <h2 className="global-txt-color px-3">个人简介</h2>
|
|
|
|
+ <div className="leading-6 text-sm text-gray-700 m-3 p-3 rounded-lg bg-[#f9fafb] dark:bg-gray-950">
|
|
|
|
+ {employeeSearch.intro}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div className="w-11/12 mx-auto rounded-lg bg-[#fff] dark:bg-gray-900 shadow-md mt-6 ">
|
|
|
|
+ <div className="p-3">
|
|
|
|
+ <h2 className="global-txt-color px-3">自我评价</h2>
|
|
|
|
+ <div className="leading-6 text-sm text-gray-700 m-3 p-3 rounded-lg bg-[#f9fafb] dark:bg-gray-950">
|
|
|
|
+ {employeeSearch.estimate}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div className="w-11/12 mx-auto rounded-lg bg-[#fff] dark:bg-gray-900 shadow-md my-6">
|
|
|
|
+ <div className="p-3">
|
|
|
|
+ <h2 className="global-txt-color px-3">技能</h2>
|
|
|
|
+ <div className="leading-6 text-sm text-gray-700 m-3 p-3 rounded-lg bg-[#f9fafb] dark:bg-gray-950">
|
|
|
|
+ {employeeSearch.skill}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ )}
|
|
</div>
|
|
</div>
|
|
);
|
|
);
|
|
}
|
|
}
|