|
@@ -2,7 +2,8 @@
|
|
|
import { getApiUrl } from "@/utils/common";
|
|
|
import { getUserSession } from "@/utils/user";
|
|
|
import { useState, useEffect } from "react";
|
|
|
-import { theme } from "antd";
|
|
|
+import type { PopconfirmProps } from "antd";
|
|
|
+import { theme, Popconfirm } from "antd";
|
|
|
import { ThemeProvider, css, cx } from "antd-style";
|
|
|
import { useTheme } from "next-themes";
|
|
|
import { ProChat, ProChatInstance } from "@ant-design/pro-chat";
|
|
@@ -11,11 +12,15 @@ import {
|
|
|
RiCalendarCloseLine,
|
|
|
RiLoader2Fill,
|
|
|
RiBookReadLine,
|
|
|
+ RiVipDiamondFill,
|
|
|
+ RiDeleteBinLine,
|
|
|
+ RiCloseFill,
|
|
|
} from "react-icons/ri";
|
|
|
import {
|
|
|
getChatSession,
|
|
|
getChatMessage,
|
|
|
getEmployeeDetail,
|
|
|
+ getUserBalance,
|
|
|
} from "@/api/client";
|
|
|
import { ChatSessionResult, EmployeeSearchResult } from "@/utils/clientsApis";
|
|
|
|
|
@@ -24,27 +29,23 @@ import {
|
|
|
ChatMessage,
|
|
|
MessageChange,
|
|
|
ChatAiModel,
|
|
|
- SetChatModelListForLocalStorage,
|
|
|
GetChatModelListForLocalStorage,
|
|
|
- SetChatLastUsedForLocalStorage,
|
|
|
+ DeleteLocalChatModelDetails,
|
|
|
UpdateLocalChatListForConversationId,
|
|
|
GetLocalChatModelDetails,
|
|
|
+ Storage_setListType,
|
|
|
+ Storage_getListType,
|
|
|
+ Storage_setAgentId,
|
|
|
+ Storage_getAgentId,
|
|
|
+ Storage_setConversationId,
|
|
|
+ Storage_getConversationId,
|
|
|
} from "@/utils/chat";
|
|
|
import { useGlobalContext } from "@/providers/GlobalProvider";
|
|
|
+import VipPage from "@/app/vip/page";
|
|
|
|
|
|
export default function Dialogue() {
|
|
|
const themeBig = useTheme();
|
|
|
- const {
|
|
|
- changeMenuIndex,
|
|
|
- loginShow,
|
|
|
- changeLoginShow,
|
|
|
- listType,
|
|
|
- changeListType,
|
|
|
- agentId,
|
|
|
- changeAgentId,
|
|
|
- conversationId,
|
|
|
- changeConversationId,
|
|
|
- } = useGlobalContext();
|
|
|
+ const { changeMenuIndex, loginShow, changeLoginShow } = useGlobalContext();
|
|
|
const [employeeSearch, setEmployeeSearch] = useState<EmployeeSearchResult>();
|
|
|
|
|
|
const [showLeftLetter, setShowLeftLetter] = useState(true);
|
|
@@ -58,24 +59,29 @@ export default function Dialogue() {
|
|
|
const [chatSessionList, setChatSessionList] = useState<ChatSessionResult[]>(
|
|
|
[]
|
|
|
);
|
|
|
+ const [showVip, setShowVip] = useState(false);
|
|
|
+ const [balance, setBalance] = useState<number>(0);
|
|
|
|
|
|
+ //历史记录和智能体列表 显示隐藏
|
|
|
const handlShowLeftLetter = () => {
|
|
|
setShowLeftLetter(!showLeftLetter);
|
|
|
};
|
|
|
|
|
|
//对话框加载聊天历史记录
|
|
|
- const chatInit = (id: string) => {
|
|
|
+ const chatInit = (id: string, agentId: number) => {
|
|
|
if (id !== "" && !id.includes("guid_0000_")) {
|
|
|
getChatMessage({
|
|
|
conversationId: id,
|
|
|
firstId: "",
|
|
|
limit: 100,
|
|
|
- agentId,
|
|
|
+ agentId: agentId,
|
|
|
}).then((data) => {
|
|
|
if (data.data.data) {
|
|
|
setIniChatMessage(MessageChange(data.data.data));
|
|
|
}
|
|
|
- setShowComponent(true);
|
|
|
+ setTimeout(() => {
|
|
|
+ setShowComponent(true);
|
|
|
+ }, 500);
|
|
|
});
|
|
|
} else {
|
|
|
setTimeout(() => {
|
|
@@ -85,47 +91,38 @@ export default function Dialogue() {
|
|
|
};
|
|
|
//历史会话 - 点击
|
|
|
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);
|
|
|
- }
|
|
|
+ //if (Storage_getConversationId() !== id) {}
|
|
|
+ Storage_setListType(0);
|
|
|
+ Storage_setConversationId(id);
|
|
|
+ setShowComponent(false);
|
|
|
+ if (id == "") {
|
|
|
+ setIniChatMessage([]);
|
|
|
+ setTimeout(() => {
|
|
|
+ setShowComponent(true);
|
|
|
+ }, 200);
|
|
|
+ } else {
|
|
|
+ chatInit(id, Storage_getAgentId());
|
|
|
}
|
|
|
};
|
|
|
//助手列表 - 点击
|
|
|
const changeChatListForLocal = (id: number) => {
|
|
|
+ loadSelectChatDetails(id);
|
|
|
var model = GetLocalChatModelDetails(id);
|
|
|
if (model !== null) {
|
|
|
setShowComponent(false);
|
|
|
setIniChatMessage([]);
|
|
|
- SetChatLastUsedForLocalStorage({
|
|
|
- listType: 1,
|
|
|
- agentId: id,
|
|
|
- conversationId: model.ConversationId,
|
|
|
- });
|
|
|
- changeConversationId(model.ConversationId);
|
|
|
- changeListType(1);
|
|
|
- changeAgentId(id);
|
|
|
+ Storage_setListType(1);
|
|
|
+ Storage_setListType(1);
|
|
|
+ Storage_setAgentId(id);
|
|
|
+ Storage_setConversationId(model.ConversationId);
|
|
|
if (model.ConversationId == "") {
|
|
|
setTimeout(() => {
|
|
|
setShowComponent(true);
|
|
|
}, 500);
|
|
|
} else {
|
|
|
- chatInit(model.ConversationId);
|
|
|
+ chatInit(model.ConversationId, id);
|
|
|
}
|
|
|
- loadChatSession("");
|
|
|
+ loadChatSession(id, "");
|
|
|
}
|
|
|
};
|
|
|
//新对话
|
|
@@ -142,17 +139,9 @@ export default function Dialogue() {
|
|
|
],
|
|
|
...chatSessionList,
|
|
|
]);
|
|
|
-
|
|
|
- SetChatLastUsedForLocalStorage({
|
|
|
- listType: 0,
|
|
|
- agentId,
|
|
|
- conversationId: newConversationId,
|
|
|
- });
|
|
|
-
|
|
|
+ Storage_setListType(0);
|
|
|
+ Storage_setConversationId(newConversationId);
|
|
|
setHistoryOrChatList(0);
|
|
|
- changeListType(0);
|
|
|
- changeConversationId(newConversationId);
|
|
|
-
|
|
|
setShowComponent(false);
|
|
|
setIniChatMessage([]);
|
|
|
setTimeout(() => {
|
|
@@ -161,6 +150,8 @@ export default function Dialogue() {
|
|
|
};
|
|
|
//设置新会话的ID
|
|
|
const setConversationId = (id: string) => {
|
|
|
+ let listType = Storage_getListType();
|
|
|
+ let conversationId = Storage_getConversationId();
|
|
|
if (listType === 0) {
|
|
|
if (conversationId.includes("guid_0000_") || conversationId == "") {
|
|
|
if (chatSessionList !== null && chatSessionList.length > 0) {
|
|
@@ -175,41 +166,62 @@ export default function Dialogue() {
|
|
|
}
|
|
|
}
|
|
|
if (listType === 1) {
|
|
|
- console.log(id);
|
|
|
- var list = UpdateLocalChatListForConversationId(agentId, id);
|
|
|
+ var list = UpdateLocalChatListForConversationId(Storage_getAgentId(), id);
|
|
|
setChatAiModelList(list);
|
|
|
}
|
|
|
- changeConversationId(id);
|
|
|
- SetChatLastUsedForLocalStorage({
|
|
|
- listType: listType,
|
|
|
- agentId,
|
|
|
- conversationId: id,
|
|
|
- });
|
|
|
+
|
|
|
+ Storage_setConversationId(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);
|
|
|
+ const loadChatSession = (agentId: number, last_id: string) => {
|
|
|
+ setTimeout(() => {
|
|
|
+ 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((chatSessionList) => [
|
|
|
- ...data.data.data,
|
|
|
- ...chatSessionList,
|
|
|
- ]);
|
|
|
+ setChatSessionList([]);
|
|
|
}
|
|
|
- } else {
|
|
|
- setChatSessionList([]);
|
|
|
+ setShowComponent(true);
|
|
|
}
|
|
|
- setShowComponent(true);
|
|
|
+ );
|
|
|
+ });
|
|
|
+ };
|
|
|
+ //加载当前智能体
|
|
|
+ const loadSelectChatDetails = (id: number) => {
|
|
|
+ getEmployeeDetail({ id: id }).then((res) => {
|
|
|
+ if (res.code == 0 && res.data !== null) {
|
|
|
+ setEmployeeSearch(res.data);
|
|
|
+ } else {
|
|
|
+ setEmployeeSearch(undefined);
|
|
|
}
|
|
|
- );
|
|
|
+ });
|
|
|
+ };
|
|
|
+ //实时获取用户积分余额
|
|
|
+ const getBalance = () => {
|
|
|
+ getUserBalance().then((res) => {
|
|
|
+ if (res.code == 0) {
|
|
|
+ setBalance(res.data.balance);
|
|
|
+ } else {
|
|
|
+ setBalance(0);
|
|
|
+ }
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
useEffect(() => {
|
|
|
changeMenuIndex(1);
|
|
|
+ let listType = Storage_getListType();
|
|
|
+ let agentId = Storage_getAgentId();
|
|
|
+ let conversationId = Storage_getConversationId();
|
|
|
+
|
|
|
if (agentId !== null && agentId > 0) {
|
|
|
//智能体进入 加载本地记录
|
|
|
getEmployeeDetail({ id: agentId }).then((res) => {
|
|
@@ -218,18 +230,18 @@ export default function Dialogue() {
|
|
|
setEmployeeSearch(res.data);
|
|
|
var list = LoadLocalChatList(res.data);
|
|
|
setChatAiModelList(list);
|
|
|
- chatInit(conversationId);
|
|
|
+ chatInit(conversationId, agentId);
|
|
|
} 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);
|
|
|
+ Storage_setListType(1);
|
|
|
+ Storage_setAgentId(list[0].id);
|
|
|
+ Storage_setConversationId(list[0].ConversationId);
|
|
|
+ chatInit(list[0].ConversationId, agentId);
|
|
|
} else {
|
|
|
- chatInit(model.ConversationId);
|
|
|
+ chatInit(model.ConversationId, agentId);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
@@ -238,17 +250,24 @@ export default function Dialogue() {
|
|
|
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);
|
|
|
+ Storage_setListType(1);
|
|
|
+ Storage_setAgentId(list[0].id);
|
|
|
+ Storage_setConversationId(list[0].ConversationId);
|
|
|
+ chatInit(list[0].ConversationId, agentId);
|
|
|
} else {
|
|
|
- chatInit(model.ConversationId);
|
|
|
+ chatInit(model.ConversationId, agentId);
|
|
|
}
|
|
|
setHistoryOrChatList(1);
|
|
|
}
|
|
|
- loadChatSession(chatSessionLastId);
|
|
|
- }, [loginShow, agentId, chatSessionLastId]);
|
|
|
+ if (conversationId !== null && conversationId !== "") {
|
|
|
+ setConversationId(conversationId);
|
|
|
+ }
|
|
|
+
|
|
|
+ loadChatSession(agentId, chatSessionLastId);
|
|
|
+
|
|
|
+ getBalance();
|
|
|
+
|
|
|
+ }, [loginShow, chatSessionLastId]);
|
|
|
|
|
|
//样式覆盖
|
|
|
const BarkCustomClassName = cx(
|
|
@@ -280,390 +299,517 @@ export default function Dialogue() {
|
|
|
`)
|
|
|
);
|
|
|
//TAGS
|
|
|
- const readTags = (value:string) => {
|
|
|
- const items = value.split(',');
|
|
|
+ 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
|
|
|
+ key={index}
|
|
|
+ className="text-sm py-1 px-2 mx-1 rounded-md bg-[#fdebaf] text-[#bc900c]"
|
|
|
+ >
|
|
|
+ {item.trim().replace('"', "").replace('"', "")}
|
|
|
</span>
|
|
|
))}
|
|
|
</ul>
|
|
|
);
|
|
|
};
|
|
|
+ //删除智能体列表中的指定记录
|
|
|
+ const confirmDeletLocalChat = (id: number) => {
|
|
|
+ var list = DeleteLocalChatModelDetails(id);
|
|
|
+ setChatAiModelList(list);
|
|
|
+ let listType = Storage_getListType();
|
|
|
+ let agentId = Storage_getAgentId();
|
|
|
+ let conversationId = Storage_getConversationId();
|
|
|
|
|
|
- return (
|
|
|
- <div
|
|
|
- className="flex justify-between items-center bg-[slate-200] dark:bg-[#000]"
|
|
|
- style={{ height: "100%" }}
|
|
|
- >
|
|
|
- {showLeftLetter && (
|
|
|
- <div
|
|
|
- className={`bg-[#f8f9fa] dark:bg-[#202123] border-r-1 border-indigo-100 dark:border-blue-950 overflow-auto scroll-smooth shrink-0`}
|
|
|
- style={{
|
|
|
- height: "calc(100vh - 5rem)",
|
|
|
- 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="flex justify-between items-center pt-2 px-2">
|
|
|
- <div>
|
|
|
- <button
|
|
|
- className="inline-flex py-1 px-1 rounded-lg items-center text-white global-bg-color"
|
|
|
- onClick={newChat}
|
|
|
- >
|
|
|
- <RiAddCircleFill className="w-6 h-6" />
|
|
|
- <span className="ml-1 pr-2 flex items-start flex-col leading-none">
|
|
|
- <span className="title-font font-medium">新对话</span>
|
|
|
- </span>
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- <div
|
|
|
- className="cursor-pointer text-gray-400 hover:text-blue-600"
|
|
|
- onClick={handlShowLeftLetter}
|
|
|
- >
|
|
|
- <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>
|
|
|
+ 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, agentId);
|
|
|
+ } else {
|
|
|
+ var list = GetChatModelListForLocalStorage();
|
|
|
+ setChatAiModelList(list);
|
|
|
+ var model = GetLocalChatModelDetails(agentId);
|
|
|
+ if (model === null && list !== null && list.length > 0) {
|
|
|
+ Storage_setListType(1);
|
|
|
+ Storage_setAgentId(list[0].id);
|
|
|
+ Storage_setConversationId(list[0].ConversationId);
|
|
|
+ chatInit(list[0].ConversationId, agentId);
|
|
|
+ } else {
|
|
|
+ chatInit(model.ConversationId, agentId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ var list = GetChatModelListForLocalStorage();
|
|
|
+ setChatAiModelList(list);
|
|
|
+ var model = GetLocalChatModelDetails(agentId);
|
|
|
+ if (model === null && list !== null && list.length > 0) {
|
|
|
+ Storage_setListType(1);
|
|
|
+ Storage_setAgentId(list[0].id);
|
|
|
+ Storage_setConversationId(list[0].ConversationId);
|
|
|
+ chatInit(list[0].ConversationId, agentId);
|
|
|
+ } else {
|
|
|
+ chatInit(model.ConversationId, agentId);
|
|
|
+ }
|
|
|
+ setHistoryOrChatList(1);
|
|
|
+ }
|
|
|
+ if (conversationId !== null && conversationId !== "") {
|
|
|
+ setConversationId(conversationId);
|
|
|
+ }
|
|
|
+ loadChatSession(agentId, chatSessionLastId);
|
|
|
+ };
|
|
|
+ const closeVipBox = () => {
|
|
|
+ setShowVip(false);
|
|
|
+ };
|
|
|
|
|
|
- {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)}
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <div
|
|
|
+ className="flex justify-between items-center bg-[slate-200] dark:bg-[#000]"
|
|
|
+ style={{ height: "100%" }}
|
|
|
+ >
|
|
|
+ {showLeftLetter && (
|
|
|
+ <div
|
|
|
+ className="bg-[#f8f9fa] dark:bg-[#202123] border-r-1 border-indigo-100 dark:border-blue-950"
|
|
|
+ style={{
|
|
|
+ height: "calc(100vh - 5rem)",
|
|
|
+ width: "20rem",
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ className={`bg-[#f8f9fa] dark:bg-[#202123] border-r-1 border-indigo-100 dark:border-blue-950 overflow-auto scroll-smooth shrink-0`}
|
|
|
+ style={{
|
|
|
+ height: "calc(100vh - 10rem)",
|
|
|
+ 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="flex justify-between items-center pt-2 px-2">
|
|
|
+ <div>
|
|
|
+ <button
|
|
|
+ className="inline-flex py-1 px-1 rounded-lg items-center text-white global-bg-color"
|
|
|
+ onClick={newChat}
|
|
|
>
|
|
|
- <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>
|
|
|
- ))}
|
|
|
+ <RiAddCircleFill className="w-6 h-6" />
|
|
|
+ <span className="ml-1 pr-2 flex items-start flex-col leading-none">
|
|
|
+ <span className="title-font font-medium">新对话</span>
|
|
|
+ </span>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ className="cursor-pointer text-gray-400 hover:text-blue-600"
|
|
|
+ onClick={handlShowLeftLetter}
|
|
|
+ >
|
|
|
+ <RiBookReadLine className="text-2xl" />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- {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 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 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" />
|
|
|
+ {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 ${
|
|
|
+ Storage_getConversationId() == item.id &&
|
|
|
+ Storage_getListType() === 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 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>
|
|
|
+ )}
|
|
|
+ {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" key={item.id}>
|
|
|
+ <div
|
|
|
+ className={`flex rounded border group ${
|
|
|
+ Storage_getAgentId() == item.id &&
|
|
|
+ Storage_getListType() === 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 relative">
|
|
|
+ <Popconfirm
|
|
|
+ title="删除提醒"
|
|
|
+ description="确定删除当前智能助手吗?"
|
|
|
+ onConfirm={() => confirmDeletLocalChat(item.id)}
|
|
|
+ okText="确定"
|
|
|
+ cancelText="取消"
|
|
|
+ >
|
|
|
+ <RiDeleteBinLine className="absolute top-0.5 right-0.5 cursor-pointer group-hover:block hidden" />
|
|
|
+ </Popconfirm>
|
|
|
+ <div className="shrink-0 inline-flex items-center justify-center h-16 overflow-hidden">
|
|
|
+ <img
|
|
|
+ src={item.avatar}
|
|
|
+ className="h-16 cursor-pointer"
|
|
|
+ onClick={() =>
|
|
|
+ changeChatListForLocal(item.id)
|
|
|
+ }
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className="flex-grow pl-2 pt-2">
|
|
|
+ <h2
|
|
|
+ className="text-base mb-1 line-clamp-1 text-ellipsis pr-5 cursor-pointer"
|
|
|
+ onClick={() =>
|
|
|
+ changeChatListForLocal(item.id)
|
|
|
+ }
|
|
|
+ >
|
|
|
+ {item.name}
|
|
|
+ </h2>
|
|
|
+ <p
|
|
|
+ className="text-sm line-clamp-1 text-ellipsis cursor-pointer"
|
|
|
+ onClick={() =>
|
|
|
+ changeChatListForLocal(item.id)
|
|
|
+ }
|
|
|
+ >
|
|
|
+ {item.estimate}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</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">
|
|
|
- <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="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>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ className="text-sm"
|
|
|
+ style={{
|
|
|
+ height: "5rem",
|
|
|
+ width: "20rem",
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div className="px-3 py-3 border-t-2 border-blue-50 shadow-sm dark:border-blue-950 dark:text-[#bc900c]">
|
|
|
+ <p className="flex items-center">
|
|
|
+ <RiVipDiamondFill className="text-[#f4a629]" />
|
|
|
+ <span className="ml-2">普通额度 {balance} 积分</span>
|
|
|
+ </p>
|
|
|
+ <p className="flex items-center mt-2">
|
|
|
+ <RiVipDiamondFill className="text-[#c81021]" />
|
|
|
+ <span className="ml-2">高级额度 {balance} 积分</span>
|
|
|
+ </p>
|
|
|
</div>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
|
|
|
- <ThemeProvider
|
|
|
- appearance={themeBig.theme}
|
|
|
- theme={{
|
|
|
- algorithm:
|
|
|
- themeBig.theme == "dark"
|
|
|
- ? theme.darkAlgorithm
|
|
|
- : theme.defaultAlgorithm,
|
|
|
- }}
|
|
|
- >
|
|
|
- <div
|
|
|
- className={`bg-[#fcfdff] dark:bg-[#202123] grow`}
|
|
|
- style={{
|
|
|
- height: "calc(100vh - 5rem)",
|
|
|
+ <ThemeProvider
|
|
|
+ appearance={themeBig.theme}
|
|
|
+ theme={{
|
|
|
+ algorithm:
|
|
|
+ themeBig.theme == "dark"
|
|
|
+ ? theme.darkAlgorithm
|
|
|
+ : theme.defaultAlgorithm,
|
|
|
}}
|
|
|
>
|
|
|
- {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,
|
|
|
- ];
|
|
|
- },
|
|
|
- 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 decoder = new TextDecoder("utf-8");
|
|
|
- const encoder = new TextEncoder();
|
|
|
+ <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,
|
|
|
+ ];
|
|
|
+ },
|
|
|
+ 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: Storage_getConversationId().includes(
|
|
|
+ "guid_0000_"
|
|
|
+ )
|
|
|
+ ? ""
|
|
|
+ : Storage_getConversationId(),
|
|
|
+ agentId: Storage_getAgentId(),
|
|
|
+ }),
|
|
|
+ }
|
|
|
+ );
|
|
|
+ if (!response.ok || !response.body) {
|
|
|
+ const errorResponseOptions = {
|
|
|
+ status: 500,
|
|
|
+ statusText: "网络错误,请重试!",
|
|
|
+ };
|
|
|
+ return new Response(null, errorResponseOptions);
|
|
|
+ } else {
|
|
|
+ const reader = response.body.getReader();
|
|
|
+ const decoder = new TextDecoder("utf-8");
|
|
|
+ const encoder = new TextEncoder();
|
|
|
|
|
|
- const readableStream = new ReadableStream({
|
|
|
- async start(controller) {
|
|
|
- function push() {
|
|
|
- reader
|
|
|
- .read()
|
|
|
- .then(({ done, value }) => {
|
|
|
- if (done) {
|
|
|
- controller.close();
|
|
|
- return;
|
|
|
- }
|
|
|
- const chunk = decoder.decode(value, {
|
|
|
- stream: true,
|
|
|
- });
|
|
|
+ const readableStream = new ReadableStream({
|
|
|
+ async start(controller) {
|
|
|
+ function push() {
|
|
|
+ reader
|
|
|
+ .read()
|
|
|
+ .then(({ done, value }) => {
|
|
|
+ if (done) {
|
|
|
+ controller.close();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const chunk = decoder.decode(value, {
|
|
|
+ stream: true,
|
|
|
+ });
|
|
|
|
|
|
- var linesArray = chunk.split("\n");
|
|
|
- for (var i = 0; i < linesArray.length - 1; i++) {
|
|
|
- const line = linesArray[i];
|
|
|
- const message = line.replace("data: ", "");
|
|
|
- const parsed = JSON.parse(message);
|
|
|
- if (!parsed.finish && parsed.answer) {
|
|
|
- controller.enqueue(
|
|
|
- encoder.encode(parsed.answer)
|
|
|
- );
|
|
|
- } else {
|
|
|
- if (parsed.finish) {
|
|
|
- setConversationId(parsed.conversation_id);
|
|
|
- }
|
|
|
- if (parsed.need_login) {
|
|
|
- changeLoginShow(true);
|
|
|
- controller.enqueue(
|
|
|
- encoder.encode("请登录后使用")
|
|
|
- );
|
|
|
- } else if (parsed.need_pay) {
|
|
|
+ var linesArray = chunk.split("\n");
|
|
|
+ for (var i = 0; i < linesArray.length - 1; i++) {
|
|
|
+ const line = linesArray[i];
|
|
|
+ const message = line.replace("data: ", "");
|
|
|
+ const parsed = JSON.parse(message);
|
|
|
+ if (!parsed.finish && parsed.answer) {
|
|
|
controller.enqueue(
|
|
|
- encoder.encode(
|
|
|
- "当前智能体需要会员才能使用,去开通:[会员套餐](/vip)"
|
|
|
- )
|
|
|
+ encoder.encode(parsed.answer)
|
|
|
);
|
|
|
+ } else {
|
|
|
+ if (parsed.finish) {
|
|
|
+ setConversationId(parsed.conversation_id);
|
|
|
+ getBalance();
|
|
|
+ }
|
|
|
+ if (parsed.need_login) {
|
|
|
+ changeLoginShow(true);
|
|
|
+ controller.enqueue(
|
|
|
+ encoder.encode("请登录后使用")
|
|
|
+ );
|
|
|
+ } else if (parsed.need_pay) {
|
|
|
+ controller.enqueue(
|
|
|
+ encoder.encode(
|
|
|
+ "当前智能体需要会员才能使用,去开通:[会员套餐](/vip)"
|
|
|
+ )
|
|
|
+ );
|
|
|
+ setShowVip(true);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- push();
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- console.error("读取流中的数据时发生错误", err);
|
|
|
- controller.error(err);
|
|
|
- });
|
|
|
- }
|
|
|
- push();
|
|
|
- },
|
|
|
- });
|
|
|
- return new Response(readableStream);
|
|
|
- }
|
|
|
- }}
|
|
|
- />
|
|
|
- )}
|
|
|
- {!showComponent && (
|
|
|
- <div className="w-full px-5 text-gray-300 flex flex-col mt-40">
|
|
|
- <div className="flex justify-center">
|
|
|
- <RiLoader2Fill className="animate-spin h-16 w-16" />
|
|
|
+ push();
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.error("读取流中的数据时发生错误", err);
|
|
|
+ controller.error(err);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ push();
|
|
|
+ },
|
|
|
+ });
|
|
|
+ return new Response(readableStream);
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {!showComponent && (
|
|
|
+ <div className="w-full px-5 text-gray-300 flex flex-col mt-40">
|
|
|
+ <div className="flex justify-center">
|
|
|
+ <RiLoader2Fill className="animate-spin h-16 w-16" />
|
|
|
+ </div>
|
|
|
+ <div className="text-center mt-4">会话加载中</div>
|
|
|
</div>
|
|
|
- <div className="text-center mt-4">会话加载中</div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- </ThemeProvider>
|
|
|
+ )}
|
|
|
+ </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>
|
|
|
+ {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>
|
|
|
- <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 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>
|
|
|
|
|
|
- <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 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>
|
|
|
|
|
|
- <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 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>
|
|
|
|
|
|
- <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 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>
|
|
|
+
|
|
|
+ {showVip && (
|
|
|
+ <div className="pay-box">
|
|
|
+ <div className="pay-mask"></div>
|
|
|
+ <div className="pay-div p-7 bg-white dark:bg-gray-900 text-base rounded container">
|
|
|
+ <RiCloseFill
|
|
|
+ className="absolute right-2.5 top-2.5 w-8 h-8 cursor-pointer transform duration-500 ease-in-out hover:scale-125 text-gray-500"
|
|
|
+ onClick={closeVipBox}
|
|
|
+ ></RiCloseFill>
|
|
|
+ <VipPage></VipPage>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
)}
|
|
|
- </div>
|
|
|
+ </>
|
|
|
);
|
|
|
}
|