import { View, Text } from "react-native";
import React, { useState, useCallback, useEffect } from "react";
import {
GiftedChat,
Send,
InputToolbar,
Composer,
Day,
LoadEarlier,
} from "react-native-gifted-chat";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useTailwind } from "tailwind-rn";
import "dayjs/locale/zh-cn";
import dayjs from "dayjs";
import { Image } from "expo-image";
import { get } from "../../../utils/storeInfo";
import Toast from "react-native-toast-message";
import requireAPI from "../../../utils/requireAPI";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import OwnBubble from "./components/OwnBubble";
const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
/*
params格式:
{
mid: item.mid,
}
*/
export default function MessageDetail({ navigation, route }) {
const tailwind = useTailwind();
const insets = useSafeAreaInsets();
const params = route.params;
const [messages, setMessages] = useState([]);
const [currentHeight, setCurrentHeight] = useState(null);
//获取本地自身数据
const [selfData, setSelfData] = useState({});
useEffect(() => {
async function getData() {
try {
const account = await get("account");
if (account) {
setSelfData(account);
}
} catch (e) {
console.error(e);
}
}
getData();
}, []);
//获取主播数据发送自动回复信息并设置页面标题
useEffect(() => {
const getData = async () => {
try {
const _data = await requireAPI(
"POST",
"/api/streamer/list_ext_by_mid",
{
body: { mid: params.mid },
}
);
if (_data.ret === -1) {
Toast.show({
type: "error",
text1: _data.msg,
topOffset: 60,
});
return;
}
navigation.setOptions({
title: _data.data.streamer_ext.name,
});
await sendAutoMessages(
_data.data.streamer_ext?.name,
_data.data.streamer_ext?.avatar?.images[0]?.urls[0],
_data.data.streamer_ext?.auto_response_message
);
} catch (error) {
console.error(error);
}
};
if (params?.mid === 1) {
navigation.setOptions({
title: "在线客服",
});
} else {
getData();
}
}, []);
//显示主播自动回复
const sendAutoMessages = async (name, avatar, content) => {
const temMessages = [
{
_id: 1,
text: content,
createdAt: new Date(),
user: {
_id: 1,
name: name,
avatar: avatar,
},
},
];
setMessages(temMessages);
};
//读取本地缓存的聊天记录
// const loadMessages = async () => {
// const accout = await get("account");
// const selfMid = accout.mid;
// const messagesCache = await get(`${selfMid}_to_${params.mid}_messages`);
// if (messagesCache) {
// setMessages(messagesCache);
// }
// };
//查询session
const [sessionId, setSessionId] = useState();
useEffect(() => {
const getSession = async () => {
try {
const account = await get("account");
const detailData = await requireAPI(
"POST",
"/api/contact_customer_service_session/list_by_mid",
{
body: { mid: account.mid },
}
);
if (detailData.ret === -1) {
Toast.show({
type: "error",
text1: detailData.msg,
topOffset: 60,
});
return;
}
if (detailData.data.session) {
setSessionId(detailData.data.session.id);
return;
}
} catch (error) {
console.error(error);
}
};
getSession();
}, []);
//创建session
const createSession = async () => {
try {
const account = await get("account");
const createData = await requireAPI(
"POST",
"/api/contact_customer_service_session/create",
{
body: { sub_mid: account.mid, obj_mid: 0 },
}
);
if (createData.ret === -1) {
Toast.show({
type: "error",
text1: createData.msg,
topOffset: 60,
});
return;
}
setSessionId(createData.data.session_id);
return createData.data.session_id;
} catch (error) {
console.error(error);
}
};
//请求历史记录
const [offset, setOffset] = useState(1);
const [more, setMore] = useState(1);
const loadEarlierHistory = async () => {
if (params?.mid !== 1) return;
if (!more) return;
if (sessionId === undefined) return;
try {
const data = await requireAPI(
"POST",
"/api/contact_customer_service/list_by_session_id",
{
body: { session_id: sessionId, offset: offset, limit: 12 },
}
);
if (data.ret === -1) {
Toast.show({
type: "error",
text1: data.msg,
topOffset: 60,
});
return;
}
setOffset(data.data.offset);
setMore(data.data.more);
const account = await get("account");
const temMessages = data.data.list.map((item) => {
if (item.predicate === 0) {
return {
_id: item.id,
createdAt: new Date(item.ct * 1000).toISOString(),
text: item.message,
mType: item.m_type,
user: {
_id: account?.mid,
name: account?.name,
avatar: account?.avatar?.images[0]?.urls[0],
},
};
} else {
return {
_id: item.id,
createdAt: new Date(item.ct * 1000).toISOString(),
text: item.message,
mType: item.m_type,
user: {
_id: 0,
name: "客服",
avatar: require("../../../assets/icon.png"),
},
};
}
});
setMessages((prev) => [...prev, ...temMessages]);
} catch (error) {
console.error(error);
}
};
//请求最新1条历史记录,如果与之前不同则加在第1条
const updateLatestHistory = async () => {
if (params?.mid !== 1) return;
if (sessionId === undefined) return;
try {
const data = await requireAPI(
"POST",
"/api/contact_customer_service/list_by_session_id",
{
body: { session_id: sessionId, offset: 0, limit: 1 },
}
);
if (data.ret === -1) {
Toast.show({
type: "error",
text1: data.msg,
topOffset: 60,
});
return;
}
const account = await get("account");
const temMessages = data.data.list.map((item) => {
if (item.predicate === 0) {
return {
_id: item.id,
createdAt: new Date(item.ct * 1000).toISOString(),
text: item.message,
mType: item.m_type,
user: {
_id: account.mid,
name: account.name,
avatar: account.avatar.images[0].urls[0],
},
};
} else {
return {
_id: item.id,
createdAt: new Date(item.ct * 1000).toISOString(),
text: item.message,
mType: item.m_type,
user: {
_id: 1,
name: "客服",
avatar: require("../../../assets/icon.png"),
},
};
}
});
setMessages((prev) => {
if (prev[0]?._id === temMessages[0]?._id) {
return prev;
} else {
// console.log("temMessages", temMessages, "prev", prev);
const newMessages = [...temMessages, ...prev].filter(
(item, index, self) =>
index === self.findIndex((t) => t.id === item.id)
);
return [...temMessages, ...prev];
}
});
if (temMessages.length > 0) {
const data2 = await requireAPI(
"POST",
"/api/contact_customer_service/read_all",
{
body: {
session_id: sessionId,
},
}
);
if (data2.ret === -1) {
Toast.show({
icon: "fail",
content: data2.msg,
position: "top",
});
return;
}
}
} catch (error) {
console.error(error);
}
};
// 轮询更新历史记录
useEffect(() => {
loadEarlierHistory();
updateLatestHistory();
// 设置轮询请求,每隔一定时间执行一次
const intervalId = setInterval(() => {
updateLatestHistory();
}, 3000); // 间隔时间为3秒
// 在组件卸载时清除定时器
return () => {
clearInterval(intervalId);
};
}, [sessionId]);
//发送私信功能
const onSend = useCallback(
async (messages = []) => {
if (!messages[0].text) {
Toast.show({
type: "error",
text1: "不可发送空内容",
topOffset: 60,
});
return;
}
//如果是第一次发送,需要创建session
let _sessionId;
if (!sessionId) _sessionId = await createSession();
//查询历史记录的时候后移一位,防止记录重复
setOffset((prev) => prev + 1);
//请求接口发送私信
try {
const data = await requireAPI(
"POST",
"/api/contact_customer_service/create",
{
body: {
session_id: sessionId ? sessionId : _sessionId,
predicate: 0,
message: messages[0].text,
},
}
);
if (data.ret === -1) {
Toast.show({
type: "error",
text1: data.msg,
topOffset: 60,
});
return;
}
updateLatestHistory();
} catch (error) {
console.error(error);
}
// //每次发送都缓存信息到本地
// addArr(`${selfData.mid}_to_${params.mid}_messages`, messages);
},
[selfData, sessionId]
);
//发送按钮样式
const renderSend = useCallback((props) => {
return (
发送
);
}, []);
//日期格式
const renderDay = useCallback((props) => {
const now = dayjs();
const isToday = now.diff(props.currentMessage.createdAt, "day") === 0;
const isYesterday = now.diff(props.currentMessage.createdAt, "day") === 1;
if (isToday) {
return ;
} else if (isYesterday) {
return ;
} else {
return ;
}
}, []);
//时间格式
const renderTime = useCallback((props) => {
return <>>;
}, []);
//输入框样式
const renderComposer = useCallback((props) => {
return (
);
}, []);
//整个输入栏样式
const renderInputToolbar = useCallback((props) => {
if (params?.mid === 1) {
return (
renderComposer(props)}
renderSend={() => renderSend(props)}
containerStyle={tailwind("p-2 bg-[#13121F] border-[#FFFFFF26]")}
primaryStyle={tailwind("items-center")}
/>
);
} else {
return ;
}
}, []);
//头像样式
const renderAvatar = useCallback((props) => {
return (
);
}, []);
//气泡样式
const renderBubble = useCallback(
(props) => {
return ;
},
[currentHeight, sessionId]
);
//加载更早信息样式
const renderLoadEarlier = useCallback(
(props) => {
return (
);
},
[more]
);
return (
loadEarlierHistory()}
showUserAvatar
showAvatarForEveryMessage
renderAvatarOnTop
messagesContainerStyle={tailwind("bg-[#13121F] pb-4")}
renderAvatar={renderAvatar}
renderDay={renderDay}
renderInputToolbar={renderInputToolbar}
renderBubble={renderBubble}
// renderMessageText={renderMessageText}
loadEarlier
renderLoadEarlier={renderLoadEarlier}
renderTime={renderTime}
messages={messages}
onSend={(messages) => onSend(messages)}
user={{
_id: selfData?.mid,
name: selfData?.name,
avatar: selfData?.avatar?.images[0]?.urls[0],
}}
/>
);
}