优化消息列表组件,新增消息内容展示,调整消息时间格式处理逻辑,更新获取消息列表的API以支持分页,提升用户体验和代码可读性。

This commit is contained in:
超级老白兔
2025-10-22 15:28:03 +08:00
parent 17e81cafc2
commit 5b9ae2b805
7 changed files with 142 additions and 134 deletions

View File

@@ -217,10 +217,7 @@ const NavCommon: React.FC<NavCommonProps> = ({ title = "触客宝" }) => {
icon={<BarChartOutlined style={{ fontSize: 18 }} />} icon={<BarChartOutlined style={{ fontSize: 18 }} />}
type="primary" type="primary"
onClick={handleMenuClick} onClick={handleMenuClick}
> ></Button>
{isWeChat() ? "功能中心" : "Ai智能客服"}
<RetweetOutlined style={{ fontSize: 18 }} />
</Button>
<Button <Button
icon={<CalendarOutlined />} icon={<CalendarOutlined />}

View File

@@ -58,8 +58,8 @@ export function getLabelsListByGroup(params) {
// } // }
//群、好友聊天记录列表 //群、好友聊天记录列表
export function getMessageList() { export function getMessageList(params: { page: number; limit: number }) {
return request("/v1/kefu/message/list", {}, "GET"); return request("/v1/kefu/message/list", params, "GET");
} }
//获取客服列表 //获取客服列表

View File

@@ -76,51 +76,11 @@
} }
.messageContent { .messageContent {
display: flex; font-size: 12px;
justify-content: space-between; color: #888;
align-items: center; overflow: hidden;
text-overflow: ellipsis;
.lastMessage { white-space: nowrap;
font-size: 12px;
color: #8c8c8c;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
position: relative;
padding-right: 5px;
height: 18px; // 添加固定高度
line-height: 18px; // 设置行高与高度一致
&::before {
content: attr(data-count);
position: absolute;
right: -5px;
top: 0;
background-color: #ff4d4f;
color: white;
border-radius: 10px;
padding: 0 6px;
font-size: 10px;
line-height: 16px;
min-width: 16px;
height: 16px;
text-align: center;
display: none;
}
&[data-count]:not([data-count=""]):not([data-count="0"]) {
&::before {
display: inline-block;
}
}
}
.onlineIndicator {
font-size: 10px;
color: #52c41a;
flex-shrink: 0;
margin-left: 8px;
}
} }
} }
} }

View File

@@ -278,6 +278,7 @@ const MessageList: React.FC<MessageListProps> = () => {
{formatWechatTime(session?.lastUpdateTime)} {formatWechatTime(session?.lastUpdateTime)}
</div> </div>
</div> </div>
<div className={styles.messageContent}>{session.content}</div>
</div> </div>
</div> </div>
</List.Item> </List.Item>

View File

@@ -13,7 +13,6 @@ import { useUserStore } from "@/store/module/user";
import { weChatGroupService, contractService } from "@/utils/db"; import { weChatGroupService, contractService } from "@/utils/db";
import { import {
loginWithToken,
getControlTerminalList, getControlTerminalList,
getContactList, getContactList,
getGroupList, getGroupList,
@@ -28,7 +27,6 @@ import {
weChatGroup, weChatGroup,
} from "@/pages/pc/ckbox/data"; } from "@/pages/pc/ckbox/data";
const { login2 } = useUserStore.getState();
//获取触客宝基础信息 //获取触客宝基础信息
export const chatInitAPIdata = async () => { export const chatInitAPIdata = async () => {
try { try {
@@ -64,60 +62,51 @@ export const chatInitAPIdata = async () => {
const countLables = await getCountLables(); const countLables = await getCountLables();
await asyncCountLables(countLables); await asyncCountLables(countLables);
//获取消息会话列表并按lastUpdateTime排序
const filterUserSessions = contractList?.filter(
v => v?.config && v.config?.chat,
);
const filterGroupSessions = groupList?.filter(
v => v?.config && v.config?.chat,
);
// 获取显示名称的辅助函数(优先 conRemark其次 nickname // 获取显示名称的辅助函数(优先 conRemark其次 nickname
const getDisplayName = (session: any) => { const getDisplayName = (session: any) => {
return session.conRemark || session.nickname || ""; return session.conRemark || session.nickname || "";
}; };
const messageList = await getMessageList(); const messageList = await getAllMessageList();
console.log(messageList);
//排序功能 //排序功能
const sortedSessions = [...filterUserSessions, ...filterGroupSessions].sort( const sortedSessions = messageList.sort((a, b) => {
(a, b) => { // 获取置顶状态
// 获取置顶状态 const aTop = a.config?.top || false;
const aTop = a.config?.top || false; const bTop = b.config?.top || false;
const bTop = b.config?.top || false;
// 首先按置顶状态排序(置顶的排在前面) // 首先按置顶状态排序(置顶的排在前面)
if (aTop !== bTop) { if (aTop !== bTop) {
return aTop ? -1 : 1; return aTop ? -1 : 1;
} }
// 如果都是置顶或都不是置顶,则按未读消息数量降序排列(未读消息多的排在前面) // 如果都是置顶或都不是置顶,则按未读消息数量降序排列(未读消息多的排在前面)
const aUnread = a.config?.unreadCount || 0; const aUnread = a.config?.unreadCount || 0;
const bUnread = b.config?.unreadCount || 0; const bUnread = b.config?.unreadCount || 0;
if (aUnread !== bUnread) { if (aUnread !== bUnread) {
return bUnread - aUnread; return bUnread - aUnread;
} }
// 如果未读消息数量相同,则按显示名称排序(字母排序) // 如果未读消息数量相同,则按显示名称排序(字母排序)
const aName = getDisplayName(a).toLowerCase(); const aName = getDisplayName(a).toLowerCase();
const bName = getDisplayName(b).toLowerCase(); const bName = getDisplayName(b).toLowerCase();
if (aName !== bName) { if (aName !== bName) {
return aName.localeCompare(bName, "zh-CN"); return aName.localeCompare(bName, "zh-CN");
} }
// 如果名称也相同,则按时间降序排列(最新的在前面) // 如果名称也相同,则按时间降序排列(最新的在前面)
// 如果lastUpdateTime不存在则将其排在最后 // 如果lastUpdateTime不存在则将其排在最后
if (!a.lastUpdateTime) return 1; if (!a.lastUpdateTime) return 1;
if (!b.lastUpdateTime) return -1; if (!b.lastUpdateTime) return -1;
const timeCompare = const timeCompare =
new Date(b.lastUpdateTime).getTime() - new Date(b.lastUpdateTime).getTime() -
new Date(a.lastUpdateTime).getTime(); new Date(a.lastUpdateTime).getTime();
return timeCompare; return timeCompare;
}, });
);
//会话数据同步 //会话数据同步
asyncChatSessions(sortedSessions); asyncChatSessions(sortedSessions);
@@ -131,6 +120,46 @@ export const chatInitAPIdata = async () => {
return []; return [];
} }
}; };
// 递归获取所有联系人列表
export const getAllMessageList = async () => {
try {
let allMessages = [];
let page = 1;
const limit = 500;
let hasMore = true;
while (hasMore) {
const Result = await getMessageList({
page,
limit,
});
const messageList = Result;
if (
!messageList ||
!Array.isArray(messageList) ||
messageList.length === 0
) {
hasMore = false;
break;
}
allMessages = [...allMessages, ...messageList];
// 如果返回的数据少于请求的数量,说明已经没有更多数据了
if (messageList.length == 0) {
hasMore = false;
} else {
page = page + 1;
}
}
return allMessages;
} catch (error) {
console.error("获取所有联系人列表失败:", error);
return [];
}
};
//发起soket连接 //发起soket连接
export const initSocket = () => { export const initSocket = () => {
// 从store获取token和accountId // 从store获取token和accountId

View File

@@ -19,7 +19,7 @@ export const createContractList = async (
const dataByLabels = []; const dataByLabels = [];
for (const label of countLables) { for (const label of countLables) {
let data; let data;
if (label.groupType === 1) { if (Number(label.groupType) === 1) {
if (label.id == 0) { if (label.id == 0) {
data = await contractService.findWhereMultiple([ data = await contractService.findWhereMultiple([
{ {
@@ -36,7 +36,7 @@ export const createContractList = async (
data = data.filter(contact => contact.wechatAccountId === kfSelected); data = data.filter(contact => contact.wechatAccountId === kfSelected);
} }
// console.log(`标签 ${label.groupName} 对应的联系人数据:`, data); // console.log(`标签 ${label.groupName} 对应的联系人数据:`, data);
} else if (label.groupType === 2) { } else if (Number(label.groupType) === 2) {
// groupType: 2, 查询 weChatGroupService // groupType: 2, 查询 weChatGroupService
if (label.id == 0) { if (label.id == 0) {
data = await weChatGroupService.findWhereMultiple([ data = await weChatGroupService.findWhereMultiple([

View File

@@ -1,55 +1,76 @@
import { Modal } from "antd-mobile"; import { Modal } from "antd-mobile";
import { getSetting } from "@/store/module/settings"; import { getSetting } from "@/store/module/settings";
export function formatWechatTime(timestamp) { import dayjs from "dayjs";
if (!timestamp) { export function formatWechatTime(lastUpdateTime: string) {
if (!lastUpdateTime) {
return ""; return "";
} }
// 处理时间戳(兼容秒级/毫秒级)
const date = new Date(
timestamp.toString().length === 10 ? timestamp * 1000 : timestamp,
);
const now = new Date();
// 获取消息时间的年月日时分 // 使用dayjs解析时间字符串处理"2025-10-22 13:21:13"格式
const messageYear = date.getFullYear(); let messageTime;
const messageMonth = date.getMonth(); try {
const messageDate = date.getDate(); // 直接解析时间字符串dayjs可以自动识别这种格式
const messageHour = date.getHours().toString().padStart(2, "0"); messageTime = dayjs(lastUpdateTime);
const messageMinute = date.getMinutes().toString().padStart(2, "0");
// 获取当前时间的年月日 // 检查日期是否有效
const nowYear = now.getFullYear(); if (!messageTime.isValid()) {
const nowMonth = now.getMonth(); console.warn("formatWechatTime: Invalid date string", lastUpdateTime);
const nowDate = now.getDate(); return "";
}
// 创建当天0点的时间对象用于比较是否同一天 } catch (error) {
const today = new Date(nowYear, nowMonth, nowDate, 0, 0, 0); console.error(
const yesterday = new Date(today); "formatWechatTime: Error processing date string",
yesterday.setDate(yesterday.getDate() - 1); lastUpdateTime,
const weekAgo = new Date(today); error,
weekAgo.setDate(weekAgo.getDate() - 6); // 7天前包括今天 );
return "";
// 消息日期(不含时间)
const messageDay = new Date(messageYear, messageMonth, messageDate, 0, 0, 0);
// 当天消息:只显示时分
if (messageDay.getTime() === today.getTime()) {
return `${messageHour}:${messageMinute}`;
} }
// 昨天消息:显示"昨天 时分" const now = dayjs();
if (messageDay.getTime() === yesterday.getTime()) {
return `昨天 ${messageHour}:${messageMinute}`; // 获取消息时间和当前时间的年份
const messageYear = messageTime.year();
const nowYear = now.year();
// 如果是去年或更早的时间,直接返回空字符串
if (messageYear < nowYear) {
return "";
} }
// 一周内消息:显示"星期X 时分" // 创建时间比较对象
if (messageDay.getTime() >= weekAgo.getTime()) { const today = now.startOf("day");
const yesterday = today.subtract(1, "day");
const messageDay = messageTime.startOf("day");
// 1. 时间是否今天,如果是就展示时和分,示例为: "13:00"
if (messageDay.isSame(today, "day")) {
return messageTime.format("HH:mm");
}
// 2. 时间是否为昨天,如果是就展示"昨天"和时与分,示例为: "昨天 13:00"
if (messageDay.isSame(yesterday, "day")) {
return `昨天 ${messageTime.format("HH:mm")}`;
}
// 3. 时间是否在本周,如果是就展示具体周几,示例为: "周一"
const startOfWeek = now.startOf("week");
const endOfWeek = now.endOf("week");
if (messageTime.isAfter(startOfWeek) && messageTime.isBefore(endOfWeek)) {
const weekdays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"]; const weekdays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
return `${weekdays[date.getDay()]} ${messageHour}:${messageMinute}`; return weekdays[messageTime.day()];
} }
// 超过一周:显示"年月日 时分" // 4. 时间是否在本月,如果是就展示月和日,示例为: "12/07"
return `${messageYear}${messageMonth + 1}${messageDate}${messageHour}:${messageMinute}`; if (messageTime.isSame(now, "month")) {
return messageTime.format("MM/DD");
}
// 5. 时间是否在本年,如果在本年就展示月和日,示例为: "12/07"
if (messageTime.isSame(now, "year")) {
return messageTime.format("MM/DD");
}
return "";
} }
/** /**
* 通用js调用弹窗Promise风格 * 通用js调用弹窗Promise风格