删除 test.jsx
This commit is contained in:
parent
e9a2245ba3
commit
55a599fa90
373
test.jsx
373
test.jsx
|
@ -1,373 +0,0 @@
|
||||||
import React, { useState, useEffect, useRef } from "react";
|
|
||||||
import { Divider, Modal, Input, Button, Menu } from "antd";
|
|
||||||
import {
|
|
||||||
Routes,
|
|
||||||
Route,
|
|
||||||
Navigate,
|
|
||||||
useNavigate,
|
|
||||||
useLocation,
|
|
||||||
} from "react-router-dom";
|
|
||||||
import baseRequest from "../../utils/baseRequest";
|
|
||||||
|
|
||||||
export default function Contact() {
|
|
||||||
//请求未读消息队列
|
|
||||||
const [unreadMessageList, setUnreadMessageList] = useState([]);
|
|
||||||
const getUnreadMessages = async () => {
|
|
||||||
if (isModalOpen) return;
|
|
||||||
try {
|
|
||||||
//获取全部未读信息
|
|
||||||
const base = baseRequest();
|
|
||||||
const response = await fetch(
|
|
||||||
"/op/contact_customer_service/list_unread_group_by_mid",
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
...base,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const data = await response.json();
|
|
||||||
if (data.ret === -1) {
|
|
||||||
alert(data.msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//获取用户头像、昵称
|
|
||||||
const userMids = data.data.list.map((item) => item.mid);
|
|
||||||
if (userMids.length === 0) {
|
|
||||||
setUnreadMessageList([]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const userResponse = await fetch("/op/account/list_others_by_mids", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
mids: userMids,
|
|
||||||
...base,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
const userData = await userResponse.json();
|
|
||||||
if (userData.ret === -1) {
|
|
||||||
alert(userData.msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//合并未读信息和用户资料数组
|
|
||||||
const combinedArray = data.data.list.map((item1) => {
|
|
||||||
const matchingItem = userData.data.list.find(
|
|
||||||
(item2) => item2.mid === item1.mid
|
|
||||||
);
|
|
||||||
return { ...item1, ...matchingItem };
|
|
||||||
});
|
|
||||||
setUnreadMessageList(combinedArray);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//控制modal是否出现
|
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
||||||
|
|
||||||
//轮询更新未读消息队列
|
|
||||||
useEffect(() => {
|
|
||||||
getUnreadMessages();
|
|
||||||
// 设置轮询请求,每隔一定时间执行一次
|
|
||||||
const intervalId = setInterval(() => {
|
|
||||||
getUnreadMessages();
|
|
||||||
}, 3000); // 间隔时间为3秒
|
|
||||||
|
|
||||||
// 在组件卸载时清除定时器
|
|
||||||
return () => {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
};
|
|
||||||
}, [isModalOpen]);
|
|
||||||
|
|
||||||
const { TextArea } = Input;
|
|
||||||
|
|
||||||
const MassageItem = ({ item }) => {
|
|
||||||
//设置消息为已读
|
|
||||||
const ids = item.contents?.map((temItem) => temItem.id);
|
|
||||||
const updateMessageStatus = async () => {
|
|
||||||
try {
|
|
||||||
const base = baseRequest();
|
|
||||||
const response = await fetch(
|
|
||||||
`/op/contact_customer_service/update_by_ids`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
is_read: 1,
|
|
||||||
ids: ids,
|
|
||||||
...base,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const data = await response.json();
|
|
||||||
if (data.ret === -1) {
|
|
||||||
alert(data.msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="flex flex-col cursor-pointer"
|
|
||||||
onClick={() => {
|
|
||||||
setModalInfo(item);
|
|
||||||
setIsModalOpen(!isModalOpen);
|
|
||||||
updateMessageStatus();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex flex-row py-2 items-center justify-between">
|
|
||||||
<div className="flex flex-row">
|
|
||||||
<img
|
|
||||||
className="w-12 h-12 rounded-full"
|
|
||||||
src={item.avatar.images[0].urls[0]}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
<div className="flex flex-col justify-around ml-2">
|
|
||||||
<p className="text-base font-bold">
|
|
||||||
<span className="text-white font-bold bg-red-400 px-2 rounded-lg">
|
|
||||||
{item.contents.length}条未读
|
|
||||||
</span>
|
|
||||||
{item.name}
|
|
||||||
</p>
|
|
||||||
<p className="text-gray-400 text-sm">
|
|
||||||
{item.contents[0].message}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-400 text-sm">
|
|
||||||
{new Date(item.contents[0].ct * 1000).toLocaleString()}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<Divider className="m-0 border-gray-400" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//保存modal中用户的mid和昵称和历史记录
|
|
||||||
const [modalInfo, setModalInfo] = useState({});
|
|
||||||
const MessageModal = () => {
|
|
||||||
//获取并保存用户聊天历史记录
|
|
||||||
const [history, setHistory] = useState([]);
|
|
||||||
//获取聊天记录,并设置为已读
|
|
||||||
const getHistory = async () => {
|
|
||||||
try {
|
|
||||||
//获取全部未读信息
|
|
||||||
const base = baseRequest();
|
|
||||||
if (!modalInfo.mid) return;
|
|
||||||
const response = await fetch(
|
|
||||||
"/op/contact_customer_service/list_by_mid",
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
mid: modalInfo.mid,
|
|
||||||
offset: 0,
|
|
||||||
limit: 100,
|
|
||||||
...base,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const data = await response.json();
|
|
||||||
if (data.ret === -1) {
|
|
||||||
alert(data.msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setHistory((prev) => {
|
|
||||||
const temData = [...data.data.list].reverse();
|
|
||||||
if (
|
|
||||||
prev.length === 0 ||
|
|
||||||
temData[temData.length - 1].id !== prev[prev.length - 1].id
|
|
||||||
) {
|
|
||||||
return temData;
|
|
||||||
} else {
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//轮询更新聊天记录
|
|
||||||
useEffect(() => {
|
|
||||||
getHistory();
|
|
||||||
// 设置轮询请求,每隔一定时间执行一次
|
|
||||||
const intervalId = setInterval(() => {
|
|
||||||
getHistory();
|
|
||||||
}, 3000); // 间隔时间为3秒
|
|
||||||
|
|
||||||
// 在组件卸载时清除定时器
|
|
||||||
return () => {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
};
|
|
||||||
}, [modalInfo]);
|
|
||||||
|
|
||||||
//将最新发送的信息设置为已读
|
|
||||||
const updateNewMessageToRead = async () => {
|
|
||||||
try {
|
|
||||||
//设置消息为已读
|
|
||||||
const base = baseRequest();
|
|
||||||
const ids = history.map((item) => {
|
|
||||||
if (item.is_read === 1) return;
|
|
||||||
return item.id;
|
|
||||||
});
|
|
||||||
if (ids.length === 0) return;
|
|
||||||
const updateResponse = await fetch(
|
|
||||||
`/op/contact_customer_service/update_by_ids`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
is_read: 1,
|
|
||||||
ids: ids,
|
|
||||||
...base,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const updateData = await updateResponse.json();
|
|
||||||
if (updateData.ret === -1) {
|
|
||||||
alert(updateData.msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendMessage = async (message) => {
|
|
||||||
//请求接口发送私信
|
|
||||||
try {
|
|
||||||
const base = baseRequest();
|
|
||||||
const response = await fetch(`/op/contact_customer_service/create`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
sub_mid: modalInfo.mid,
|
|
||||||
obj_mid: base.b_mid,
|
|
||||||
predicate: 1,
|
|
||||||
message: message,
|
|
||||||
...base,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
const data = await response.json();
|
|
||||||
if (data.ret === -1) {
|
|
||||||
alert(data.msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setMessageContent("");
|
|
||||||
getHistory();
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//保存输入框内容
|
|
||||||
const [messageContent, setMessageContent] = useState("");
|
|
||||||
|
|
||||||
//自动滚动到聊天记录底部
|
|
||||||
const modalContentRef = useRef();
|
|
||||||
useEffect(() => {
|
|
||||||
if (modalContentRef.current) {
|
|
||||||
modalContentRef.current.scrollTop =
|
|
||||||
modalContentRef.current.scrollHeight;
|
|
||||||
}
|
|
||||||
}, [history]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
title={`与【${modalInfo.name}】的聊天`}
|
|
||||||
footer={null}
|
|
||||||
open={isModalOpen}
|
|
||||||
onCancel={async () => {
|
|
||||||
setIsModalOpen(false);
|
|
||||||
await updateNewMessageToRead();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
ref={modalContentRef}
|
|
||||||
className="flex flex-col h-96 overflow-y-scroll"
|
|
||||||
>
|
|
||||||
{history?.map((item, index) => {
|
|
||||||
if (item.predicate === 1) {
|
|
||||||
return (
|
|
||||||
<div key={index} className="flex flex-row justify-end my-1">
|
|
||||||
<div className="flex flex-col mr-2 p-2 bg-gray-200 rounded-lg">
|
|
||||||
<p className="text-base">{item.message}</p>
|
|
||||||
<p className="text-gray-400 text-sm text-end mt-2">
|
|
||||||
{new Date(item.ct * 1000).toLocaleString()}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<img
|
|
||||||
className="w-12 h-12 rounded-full"
|
|
||||||
src="https://s2.loli.net/2023/08/03/mu51haYNUOPXkqR.png"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<div key={index} className="flex flex-row justify-start my-1">
|
|
||||||
<img
|
|
||||||
className="w-12 h-12 rounded-full"
|
|
||||||
src={modalInfo.avatar.images[0].urls[0]}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
<div className="flex flex-col ml-2 p-2 bg-gray-200 rounded-lg">
|
|
||||||
<p className="text-base">{item.message}</p>
|
|
||||||
<p className="text-gray-400 text-sm text-start mt-2">
|
|
||||||
{new Date(item.ct * 1000).toLocaleString()}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<TextArea
|
|
||||||
value={messageContent}
|
|
||||||
onChange={(e) => setMessageContent(e.target.value)}
|
|
||||||
className="mt-2"
|
|
||||||
rows={2}
|
|
||||||
/>
|
|
||||||
<div className="flex flex-col mt-2">
|
|
||||||
<Button
|
|
||||||
onClick={() => sendMessage(messageContent)}
|
|
||||||
className="w-24 self-end"
|
|
||||||
type="primary"
|
|
||||||
>
|
|
||||||
发送
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section className="p-4">
|
|
||||||
<div>
|
|
||||||
{unreadMessageList.length === 0 && <h1>暂无未读消息</h1>}
|
|
||||||
{unreadMessageList?.map((item, index) => (
|
|
||||||
<MassageItem key={index} item={item} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<MessageModal />
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
Loading…
Reference in New Issue