press-next
Version:
Vue3 组件库,支持 Composition API
214 lines (172 loc) • 4.76 kB
text/typescript
import { MESSAGE_TYPE_MAP } from './config';
import { formatTime, isJsonStr } from './helper';
const INSERT_TIME_DURATION = 1 * 60 * 60;
export interface UserInfo {
uid: string;
avatar: string;
nick: string;
isOwner: boolean;
laddergrade?: string;
cardInfo?: {
phone?: string | number;
wx_account?: string | number;
qq_account?: string | number;
}
}
export interface RawMessageItem {
time: number;
from: string;
to: string;
payload?: {
text: string;
};
ID?: string;
isCustomFail: boolean;
isPeerRead: boolean;
isRevoked: boolean;
}
export interface ParsedMessageItemContent {
text: string;
title?: string;
link?: string;
picUrl?: string;
phone?: string | number;
wechat?: string | number;
qq?: string | number;
}
export interface ParsedMessageItem {
id: string;
time: string;
timeStamp: number;
msgType: string;
parsedText: Record<string, any>;
from: string;
to: string;
isPeerRead: boolean;
isCustomFail: boolean;
avatar: string;
nick: string;
uid: string;
isMine: boolean;
isOwner: boolean;
laddergrade?: string;
content: ParsedMessageItemContent;
isRevoked: boolean;
}
function formatMessageContent(message: string, userInfo?: UserInfo): ParsedMessageItemContent {
if (!isJsonStr(message)) {
return { text: message };
}
let info: {
title?: string;
content?: string;
jumpUrl?: string;
picUrl?: string;
} = {};
try {
info = JSON.parse(message);
} catch (e) {
return { text: message };
}
return {
title: info.title || '',
text: info.content || '',
link: info.jumpUrl || '',
picUrl: info.picUrl || '',
phone: userInfo?.cardInfo?.phone || '',
wechat: userInfo?.cardInfo?.wx_account || '',
qq: userInfo?.cardInfo?.qq_account || '',
};
}
function addTimeMsg(list: Array<{
timeStamp: number;
msgType: string;
id: string;
content: {
text: string;
}
}>, lastTime: number) {
if (!list.length) return;
let recentTime = list[list.length - 1].timeStamp;
if (lastTime) {
recentTime = lastTime;
}
// 倒序插入,如果从前往后插,index会变
for (let i = list.length - 1;i >= 0;i--) {
const item = list[i];
if (recentTime > item.timeStamp + INSERT_TIME_DURATION) {
const nextTime = list[i + 1].timeStamp;
list.splice(i + 1, 0, {
msgType: MESSAGE_TYPE_MAP.TIME,
id: `id-time-${i + 1}-${nextTime}`,
timeStamp: nextTime,
content: {
text: formatTime(nextTime),
},
});
recentTime = item.timeStamp;
}
}
// 在第一个之前插入时间tag
// 如果传入lastTime,说明是接收信息,则只有在这条消息超过 INSERT_TIME_DURATION 后才再次插入tag
if (!lastTime || list?.[0]?.timeStamp > lastTime + INSERT_TIME_DURATION) {
list.splice(0, 0, {
msgType: MESSAGE_TYPE_MAP.TIME,
id: `id-time-0-${list[0].id}`,
timeStamp: list[0].timeStamp,
content: {
text: formatTime(list[0].timeStamp),
},
});
}
}
function deleteRevokedMessages<T extends {
isRevoked?: boolean;
}>(list: Array<T>) {
return list = list.filter(item => !item.isRevoked);
}
export function baseFormatMessageDetailList(
list: Array<RawMessageItem>,
myInfo: UserInfo,
oppositeInfo: UserInfo,
lastTimeStampTag: number,
): ParsedMessageItem[] {
let mList = list as unknown as ParsedMessageItem[];
mList = deleteRevokedMessages(mList) as unknown as ParsedMessageItem[];
mList = (mList as unknown as RawMessageItem[])
.map((item) => {
const { time, from, to, payload, isPeerRead, ID: id, isCustomFail, isRevoked } = item;
const { text = '' } = payload || {};
const isMine = from === myInfo.uid;
const uid = isMine ? myInfo.uid : oppositeInfo.uid;
let parsedText = {};
if (text && isJsonStr(text)) {
try {
parsedText = JSON.parse(text);
} catch (e) {
parsedText = {};
}
}
return {
id: `id-${id}`,
time: formatTime(time as unknown as number),
timeStamp: (time as unknown as number),
msgType: MESSAGE_TYPE_MAP.MESSAGE_TEXT,
parsedText,
from,
to,
isPeerRead,
isCustomFail,
avatar: isMine ? myInfo.avatar : oppositeInfo.avatar,
nick: isMine ? myInfo.nick : oppositeInfo.nick,
uid,
isMine,
isOwner: isMine ? myInfo.isOwner : oppositeInfo.isOwner,
laddergrade: isMine ? myInfo.laddergrade : oppositeInfo.laddergrade,
content: formatMessageContent(text, isMine ? myInfo : oppositeInfo),
isRevoked,
};
});
addTimeMsg(mList, lastTimeStampTag);
return mList;
}