tiefen_space_h5/app/messageDetail/page.js

487 lines
14 KiB
JavaScript
Raw Normal View History

2024-07-03 19:59:39 +08:00
"use client";
2024-07-11 23:57:26 +08:00
import React, { useState, useRef, useEffect, useCallback } from "react";
2024-07-03 19:59:39 +08:00
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleLeft } from "@fortawesome/free-solid-svg-icons";
2024-07-12 22:52:48 +08:00
import { Input, Button, Toast, Avatar, DotLoading } from "antd-mobile";
2024-07-24 20:20:09 +08:00
import { useRouter, useSearchParams } from "next/navigation";
2024-07-11 23:57:26 +08:00
import { get } from "@/utils/storeInfo";
2024-07-22 16:07:41 +08:00
import requireAPI from "@/utils/requireAPI";
2024-07-11 23:57:26 +08:00
import { formatDeadline } from "@/utils/tools";
2024-07-24 20:20:09 +08:00
import { getStreamerDetailInfo } from "@/api/space";
2024-07-03 19:59:39 +08:00
/*
params格式
{
mid: item.mid,
}
*/
export default function MessageDetail({}) {
2024-07-11 23:57:26 +08:00
// const [hasMore, setHasMore] = useState(true);
2024-07-03 19:59:39 +08:00
const router = useRouter();
2024-07-24 20:20:09 +08:00
const searchParams = useSearchParams();
2024-07-11 23:57:26 +08:00
const [oldMessages, setOldMessages] = useState([]);
const [messages, setMessages] = useState([]);
const [handledmessages, setHandledmessages] = useState([]);
const [sessionId, setSessionId] = useState();
const [userInfo, setUserInfo] = useState(null);
const [newMessage, setNewMessage] = useState("");
2024-07-12 22:52:48 +08:00
const [loading, setLoading] = useState(false);
2024-07-11 23:57:26 +08:00
const [offset, setOffset] = useState(0);
const [more, setMore] = useState(1);
const scrollBox = useRef();
const toScrollBottom = useRef(0);
useEffect(() => {
const userData = get("account");
const mid = searchParams.get("mid");
2024-07-24 20:20:09 +08:00
if (mid) {
getStreamerDetailInfo(Number(mid)).then((data) => {
setMessages([
[
{
predicate: 1,
_id: 1,
createdAt: new Date() / 1000,
text: data?.streamer_ext.auto_response_message,
user: {
_id: 0,
name: data?.streamer_ext.name,
avatar: data?.streamer_ext?.avatar?.images[0]?.urls[0],
},
},
],
]);
});
2024-07-24 20:20:09 +08:00
} else {
setUserInfo(userData);
getSession(userData.mid);
}
2024-07-11 23:57:26 +08:00
}, []);
2024-07-12 22:52:48 +08:00
useEffect(() => {
const intervalId = setInterval(() => {
// console.log("oldMessages[0]", oldMessages[0]);
if (oldMessages[0]) {
updateMessages(oldMessages[0]?.id, 0, oldMessages);
// toScrollBottom.current = 1;
2024-07-12 22:52:48 +08:00
}
}, 3000); // 间隔时间为3秒
// 在组件卸载时清除定时器
return () => {
clearInterval(intervalId);
};
}, [oldMessages]);
2024-07-11 23:57:26 +08:00
useEffect(() => {
if (toScrollBottom.current) {
2024-07-22 17:55:52 +08:00
scrollBox.current?.scrollTo(0, scrollBox.current.scrollHeight + 50);
2024-07-11 23:57:26 +08:00
toScrollBottom.current = 0;
}
2024-07-15 20:00:44 +08:00
}, [messages]);
2024-07-11 23:57:26 +08:00
useEffect(() => {
if (sessionId && userInfo.mid) {
loadEarlierHistory().then((res) => {
setMessages((old) => {
toScrollBottom.current = 1;
return res;
});
2024-07-03 19:59:39 +08:00
});
2024-07-11 23:57:26 +08:00
}
}, [sessionId]);
//查询session
const getSession = async (mid) => {
2024-07-22 17:55:52 +08:00
setLoading(true);
2024-07-11 23:57:26 +08:00
try {
2024-07-22 17:55:52 +08:00
const data = await requireAPI(
"POST",
"/api/contact_customer_service_session/list_by_mid",
{
2024-07-11 23:57:26 +08:00
body: {
mid: Number(mid),
2024-07-03 19:59:39 +08:00
},
2024-07-22 17:55:52 +08:00
}
);
2024-07-11 23:57:26 +08:00
if (data.ret === -1) {
2024-07-03 19:59:39 +08:00
Toast.show({
2024-07-06 11:05:19 +08:00
icon: "fail",
content: data.msg,
position: "top",
2024-07-03 19:59:39 +08:00
});
2024-07-11 23:57:26 +08:00
}
2024-07-22 17:55:52 +08:00
setLoading(false);
2024-07-11 23:57:26 +08:00
if (data.data.session) {
setSessionId(data.data.session.id);
2024-07-22 17:55:52 +08:00
} else {
//如果是第一次发送需要创建session
createSession(mid);
2024-07-03 19:59:39 +08:00
}
2024-07-11 23:57:26 +08:00
} catch (error) {
2024-09-09 15:34:31 +08:00
// console.error(error);
2024-07-11 23:57:26 +08:00
}
};
//创建session
2024-07-22 17:55:52 +08:00
const createSession = async (mid) => {
setLoading(true);
2024-07-11 23:57:26 +08:00
try {
2024-07-22 17:55:52 +08:00
const data = await requireAPI(
"POST",
"/api/contact_customer_service_session/create",
{
2024-07-11 23:57:26 +08:00
body: {
sub_mid: Number(mid),
obj_mid: 0,
},
2024-07-22 17:55:52 +08:00
}
);
2024-07-11 23:57:26 +08:00
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
}
setSessionId(data.data.session_id);
2024-07-22 17:55:52 +08:00
setLoading(false);
2024-07-11 23:57:26 +08:00
} catch (error) {
2024-09-09 15:34:31 +08:00
// console.error(error);
2024-07-11 23:57:26 +08:00
}
};
//请求历史记录
const loadEarlierHistory = async () => {
if (!more) return;
try {
2024-07-22 17:55:52 +08:00
setLoading(true);
const data = await requireAPI(
"POST",
"/api/contact_customer_service/list_by_session_id",
{
2024-07-11 23:57:26 +08:00
body: {
session_id: sessionId,
offset: offset,
limit: 12,
},
2024-07-22 17:55:52 +08:00
}
);
2024-07-11 23:57:26 +08:00
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
2024-07-03 19:59:39 +08:00
return;
}
2024-07-11 23:57:26 +08:00
setOffset(data.data.offset);
setMore(data.data.more);
2024-07-22 17:55:52 +08:00
let mathNewMessages = handleData([...oldMessages, ...data.data.list]);
2024-07-11 23:57:26 +08:00
// setMessages((prev) => [...prev, ...temMessages]);
2024-07-22 17:55:52 +08:00
setLoading(false);
2024-07-11 23:57:26 +08:00
return mathNewMessages;
2024-07-03 19:59:39 +08:00
} catch (error) {
2024-09-09 15:34:31 +08:00
// console.error(error);
2024-07-03 19:59:39 +08:00
}
};
2024-07-11 23:57:26 +08:00
//发送私信功能
const onSend = useCallback(
async (message, lastId, oldArr) => {
if (message == "") {
2024-07-23 20:56:25 +08:00
// Toast.show({
// icon: "error",
// content: "不可发送空内容",
// position: "top",
// });
2024-07-11 23:57:26 +08:00
return;
}
//查询历史记录的时候后移一位,防止记录重复
setOffset((prev) => prev + 1);
//请求接口发送私信
try {
2024-07-22 17:55:52 +08:00
const data = await requireAPI(
"POST",
"/api/contact_customer_service/create",
{
2024-07-11 23:57:26 +08:00
body: {
session_id: sessionId,
predicate: 0,
message,
},
2024-07-22 17:55:52 +08:00
}
);
2024-07-11 23:57:26 +08:00
if (data.ret === -1) {
Toast.show({
icon: "error",
content: data.msg,
position: "top",
});
return;
}
// updateLatestHistory();
2024-07-12 22:52:48 +08:00
// console.log("oldArr", oldArr);
2024-07-22 17:55:52 +08:00
updateMessages(lastId, 0, oldArr).then((res) => {
2024-07-12 22:52:48 +08:00
setNewMessage("");
toScrollBottom.current = 1;
});
2024-07-11 23:57:26 +08:00
} catch (error) {
2024-09-09 15:34:31 +08:00
// console.error(error);
2024-07-11 23:57:26 +08:00
}
// //每次发送都缓存信息到本地
// addArr(`${selfData.mid}_to_${params.mid}_messages`, messages);
},
[userInfo, sessionId]
);
// async function doRefresh() {
// await sleep(1000);
// Toast.show({
// icon: "fail",
// content: "刷新失败",
// });
// throw new Error("刷新失败");
// }
2024-07-03 19:59:39 +08:00
async function loadMore() {
2024-07-11 23:57:26 +08:00
if (sessionId && userInfo.mid && offset && more) {
const append = await loadEarlierHistory();
if (append) {
// setMessages((val) => [...val, ...append]);
setMessages(append);
// setHasMore(append.length > 0);
}
}
2024-07-03 19:59:39 +08:00
}
2024-07-11 23:57:26 +08:00
const handleData = (list) => {
// console.log("list", list);
const account = get("account");
const temMessages = list.map((item) => {
if (item.predicate === 0) {
return {
predicate: item.predicate,
_id: item.id,
// createdAt: new Date(item.ct * 1000).toISOString(),
createdAt: item.ct,
text: item.message,
user: {
_id: account?.mid,
name: account?.name,
avatar: account?.avatar?.images[0]?.urls[0],
},
};
} else {
return {
predicate: item.predicate,
_id: item.id,
createdAt: item.ct,
text: item.message,
user: {
_id: 0,
name: "客服",
2024-07-30 22:53:41 +08:00
avatar: process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/images/icon.png",
2024-07-11 23:57:26 +08:00
},
};
}
});
2024-07-12 22:52:48 +08:00
// console.log("handledmessages......", handledmessages);
// console.log("[...messages, ...temMessages]", temMessages);
setHandledmessages(temMessages);
setOldMessages(list);
let newMessages = temMessages.reverse();
2024-07-11 23:57:26 +08:00
let mathNewMessages = newMessages.reduce(
(accumulator, currentValue, index, sourceArray) => {
// console.log(
// accumulator.time,
// "----",
// currentValue.createdAt,
// "---",
// index
// );
if (accumulator.time > currentValue.createdAt) {
let newData = {
...accumulator,
time: accumulator.time,
messages: [...accumulator.messages, currentValue],
totalArr:
index == sourceArray.length - 1
? [
...accumulator.totalArr,
[...accumulator.messages, currentValue],
]
: [...accumulator.totalArr],
};
return newData;
} else {
let newData = {
...accumulator,
time: currentValue.createdAt + 60 * 3,
messages: [currentValue],
totalArr:
index == sourceArray.length - 1
? [
...accumulator.totalArr,
accumulator.messages,
[currentValue],
]
: [...accumulator.totalArr, accumulator.messages],
};
return newData;
}
},
{ time: newMessages[0]?.createdAt + 60 * 3, messages: [], totalArr: [] }
);
return mathNewMessages.totalArr;
};
const updateMessages = async (lastId, currentOffset, oldArr) => {
2024-07-12 22:52:48 +08:00
// console.log("lastId", lastId);
2024-07-11 23:57:26 +08:00
try {
2024-07-22 17:55:52 +08:00
const data = await requireAPI(
"POST",
"/api/contact_customer_service/list_by_session_id",
{
2024-07-11 23:57:26 +08:00
body: {
session_id: sessionId,
offset: currentOffset,
limit: 12,
},
2024-07-22 17:55:52 +08:00
}
);
2024-07-11 23:57:26 +08:00
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
return;
}
let newData = data.data.list.filter((element) => {
return element.id > lastId;
});
2024-07-12 22:52:48 +08:00
// console.log("[...messages,...newData]", [...newData]);
2024-07-22 17:55:52 +08:00
let mathNewMessages = handleData([...newData, ...oldArr]);
2024-07-11 23:57:26 +08:00
setMessages((old) => {
toScrollBottom.current = 1;
return mathNewMessages;
});
2024-07-22 17:55:52 +08:00
return;
2024-07-11 23:57:26 +08:00
} catch (error) {
console.error(error);
}
};
2024-07-03 19:59:39 +08:00
return (
2024-07-11 23:57:26 +08:00
<div className="bg-[#13121F] h-screen overflow-y-auto" ref={scrollBox}>
<div className="p-4 fixed top-0 z-10 w-full bg-deepBg">
2024-07-03 19:59:39 +08:00
<div className="flex items-center justify-center absolute">
<FontAwesomeIcon
icon={faAngleLeft}
style={{ maxWidth: "12px" }}
2024-07-03 19:59:39 +08:00
size="xl"
onClick={() => {
router.back();
}}
/>
</div>
<p className="text-base text-center">
{!searchParams.get("mid") ? "在线客服" : messages?.[0]?.[0].user.name}
</p>
2024-07-03 19:59:39 +08:00
</div>
<div>
2024-07-11 23:57:26 +08:00
<div className="my-[57px]">
{!searchParams.get("mid") && (
<div className="flex justify-center py-2">
<div className="px-3 py-2 rounded-full bg-[#FFFFFF1A]">
{loading ? (
<DotLoading />
) : more ? (
<span onClick={loadMore}>查看更早</span>
) : (
<span>无更早消息</span>
)}
</div>
2024-07-12 22:52:48 +08:00
</div>
)}
2024-07-11 23:57:26 +08:00
<ul className="py-2">
{messages?.map((item, index) => (
<li key={index}>
<p className="my-2 text-center">
{formatDeadline(item[0].createdAt)}
</p>
<ul className="px-4 overflow-y-auto scrollbarBox_hidden">
{item.map((it) => (
<li key={it?._id} className="py-3 rounded-lg ">
<div className="flex w-full">
{it?.predicate == 1 ? (
2024-07-25 19:52:30 +08:00
<div className="flex justify-start w-full">
2024-07-11 23:57:26 +08:00
<Avatar
2024-07-25 19:52:30 +08:00
className="mr-2 w-[32px] h-[32px]"
2024-07-11 23:57:26 +08:00
style={{ "--border-radius": "50px" }}
width={32}
height={32}
src={it?.user.avatar}
/>
<div
2024-07-25 19:52:30 +08:00
className="rounded-lg py-2 px-3 bg-blue-500 break-words"
style={{
borderTopLeftRadius: 0,
maxWidth: "calc(100% - 32px - 0.75rem)",
}}
2024-07-11 23:57:26 +08:00
>
{it?.text}
</div>
</div>
) : (
2024-07-25 19:52:30 +08:00
<div className="flex justify-end w-full">
2024-07-11 23:57:26 +08:00
<div
2024-07-25 19:52:30 +08:00
className="max-w-full rounded-lg py-2 px-3 bg-blue-500 break-words"
style={{
borderTopRightRadius: 0,
maxWidth: "calc(100% - 32px - 0.75rem)",
}}
2024-07-11 23:57:26 +08:00
>
{it?.text}
</div>
<Avatar
2024-07-30 22:53:41 +08:00
className="ml-2 w-[32px] h-[32px]"
2024-07-11 23:57:26 +08:00
style={{ "--border-radius": "50px" }}
width={32}
height={32}
src={it?.user?.avatar}
/>
</div>
)}
</div>
</li>
))}
</ul>
</li>
))}
{}
{/* <InfiniteScroll loadMore={loadMore} hasMore={more} /> */}
</ul>
2024-07-03 19:59:39 +08:00
</div>
2024-07-30 22:53:41 +08:00
{!searchParams.get("mid") && (
2024-07-24 20:20:09 +08:00
<div className="w-full h-16 fixed bottom-0 grid grid-cols-[1fr_68px] bg-black items-center p-2 border-t-2 border-[#ffffff2a]">
<div className="rounded bg-[#222036] px-4 py-2 mr-2">
<Input
placeholder="输入新消息"
className=""
value={newMessage}
onChange={setNewMessage}
style={{ "--font-size": "16px" }}
2024-07-24 20:20:09 +08:00
/>
</div>
<Button
size="middle"
block
onClick={() =>
onSend(newMessage, oldMessages[0]?.id || -1, oldMessages)
}
style={{ "--background-color": "#FF669E", color: "#FFFFFF" }}
>
发送
</Button>
2024-07-03 19:59:39 +08:00
</div>
2024-07-24 20:20:09 +08:00
)}
2024-07-03 19:59:39 +08:00
</div>
</div>
);
}