1.jpg (116.6 KB, 下载次数: 0)
下载附件 保存到相册
22 天前 上传
project_files.png (73.44 KB, 下载次数: 0)
2.jpg (116.69 KB, 下载次数: 0)
3.png (88 KB, 下载次数: 0)
4.png (155.19 KB, 下载次数: 1)
5.png (119.58 KB, 下载次数: 0)
6.png (30.19 KB, 下载次数: 0)
7.png (61.28 KB, 下载次数: 0)
8.png (39.78 KB, 下载次数: 0)
/** * 仿照微信中的消息时间显示逻辑,将时间戳(单位:毫秒)转换为友好的显示格式. * * 1)7天之内的日期显示逻辑是:今天、昨天(-1d)、前天(-2d)、星期?(只显示总计7天之内的星期数,即<=-4d); * 2)7天之外(即>7天)的逻辑:直接显示完整日期时间。 * @param timestamp 时间戳(单位:毫秒),形如:1550789954260 * @param mustIncludeTime true表示输出的格式里一定会包含“时间:分钟” * ,否则不包含(参考微信,不包含时分的情况,用于首页“消息”中显示时) * @param timeWithSegmentStr 本参数仅在mustIncludeTime=true时有生效,表示在时间字符串前带上“上午”、“下午”、“晚上”这样的描述 * * @return 输出格式形如:“刚刚”、“10:30”、“昨天 12:04”、“前天 20:51”、“星期二”、“2019/2/21 12:09”等形式 * @author Jack Jiang([url=http://www.52im.net/thread-2792-1-1.html]http://www.52im.net/thread-2792-1-1.html[/url]) */ static getTimeStringAutoShort2(timestamp: number, mustIncludeTime: boolean, timeWithSegmentStr: boolean): string { // 当前时间 let currentDate: Date = new Date(); // 目标判断时间 let srcDate: Date = new Date(timestamp); let currentYear: number = currentDate.getFullYear(); let currentMonth: number = (currentDate.getMonth()+1); let currentDateD: number = currentDate.getDate(); let srcYear: number = srcDate.getFullYear(); let srcMonth: number = (srcDate.getMonth()+1); let srcDateD: number = srcDate.getDate(); let ret: string = ''; // 要额外显示的时间分钟 let timeExtraStr = ''; if(mustIncludeTime) { // let timeExtraStr = (mustIncludeTime ? " " + _formatDate(srcDate, "hh:mm") : ""); timeExtraStr = " "+ToolKits.getTimeHH24Human(srcDate, timeWithSegmentStr); } // 当年 if(currentYear === srcYear) { let currentTimestamp: number = currentDate.getTime(); let srcTimestamp: number = timestamp; // 相差时间(单位:毫秒) let deltaTime: number = (currentTimestamp-srcTimestamp); // 当天(月份和日期一致才是) if(currentMonth === srcMonth && currentDateD === srcDateD) { // // 时间相差60秒以内 // if(deltaTime < 60 * 1000) // ret = "刚刚"; // // 否则当天其它时间段的,直接显示“时:分”的形式 // else // ret = _formatDate(srcDate, "hh:mm"); // 当天只需要显示时间分钟,且必须显示“上午”、“下午”这样的时间段描述 ret = ToolKits.getTimeHH24Human(srcDate, true); } // 当年 && 当天之外的时间(即昨天及以前的时间) else { // 昨天(以“现在”的时候为基准-1天) let yesterdayDate:Date = new Date(); yesterdayDate.setDate(yesterdayDate.getDate()-1); // 前天(以“现在”的时候为基准-2天) let beforeYesterdayDate: Date = new Date(); beforeYesterdayDate.setDate(beforeYesterdayDate.getDate()-2); // 用目标日期的“月”和“天”跟上方计算出来的“昨天”进行比较,是最为准确的(如果用时间戳差值 // 的形式,是不准确的,比如:现在时刻是2019年02月22日1:00、而srcDate是2019年02月21日23:00, // 这两者间只相差2小时,直接用“deltaTime/(3600 * 1000)” > 24小时来判断是否昨天,就完全是扯蛋的逻辑了) if(srcMonth === (yesterdayDate.getMonth()+1) && srcDateD === yesterdayDate.getDate()) { ret = "昨天"+timeExtraStr;// -1d } // “前天”判断逻辑同上 else if(srcMonth === (beforeYesterdayDate.getMonth()+1) && srcDateD === beforeYesterdayDate.getDate()) { ret = "前天" + timeExtraStr; // -2d } else{ // 跟当前时间相差的小时数 let deltaHour: number = (deltaTime/(3600 * 1000)); // 如果小于或等 7*24小时就显示星期几 if (deltaHour <= 7*24){ let weekday = new Array<string>(7); weekday[0]="星期日"; weekday[1]="星期一"; weekday[2]="星期二"; weekday[3]="星期三"; weekday[4]="星期四"; weekday[5]="星期五"; weekday[6]="星期六"; // 取出当前是星期几 let weedayDesc: string = weekday[srcDate.getDay()]; ret = weedayDesc + timeExtraStr; } // 否则直接显示完整日期时间 else ret = ToolKits.formatDate(srcDate, "M月d日")+timeExtraStr; } } } // 往年 else{ ret = ToolKits.formatDate(srcDate, "yy年M月d日")+timeExtraStr; } return ret; }
/** * 聊天消息的缓存数据管理提供者(集中管理所有的聊天消息和指令,消息来源为网络层通信数据包和本地发出的包 * ,消息显示方式通过MessagesDataSource与UI界面进行解偶显示)。 * * 代码参考自IM产品RainbowChat:[url=http://www.52im.net/thread-19-1-1.html]http://www.52im.net/thread-19-1-1.html[/url] * * @author Jack Jiang([url=http://www.52im.net/thread-2792-1-1.html]http://www.52im.net/thread-2792-1-1.html[/url]) */ export default class MessagesProvider { /** 聊天界面中,消息的显示时间间隔(单位:毫秒):默认是2分钟内的消息只在第一条消息上显示时间,否则会再次显示时间 */ // 参考资料:[url=http://www.52im.net/thread-3008-1-1.html#40]http://www.52im.net/thread-3008-1-1.html#40[/url] private static readonly CHATTING_MESSAGE_SHOW_TIME_INTERVAL: number = 2 * 60 * 1000; /** 真正的聊天软件中,此处应改造为<key=uid, value=Array<Message> >这样的Map集合,用于按uid分别存储与各好友的聊天消息 */ private messages: Array<Message> = []; /** * 加入一条新消息。 * * @param m 消息对象 */ putMessage(m: Message): void { // 以下代码用于判断并实现仿微信的只显示2分钟内聊天消息的时间标识(参考资料:[url=http://www.52im.net/thread-3008-1-1.html#40]http://www.52im.net/thread-3008-1-1.html#40[/url]) let previousMessage: Message | undefined = undefined; let messagesSize: number = this.messages.length; if (messagesSize > 0) { previousMessage = this.messages[messagesSize - 1]; } MessagesProvider.setMessageShowTopTime(m, previousMessage); // 将此新消息对象放入数据模型(列表) this.messages.push(m); // 通知应用层更新ui IMClientManager.getInstance().getEmitter().emit(UIEvent.UIEVENT_messageAdded, this.messages.length - 1); } /** * 获得消息数据缓存集合。 * * @returns 消息数据缓存集合 */ getMessages(): Array<Message> { return this.messages; } /** * 添加一条系统消息(显示在聊天列表中)。 * * @param content 消息内容 */ addSystemMessage(content: string): void { let m: Message = Message.createChatMsgEntity_INCOME_SYSTEAMINFO('0', content, 0); this.putMessage(m); } /** * 更新指定指纹码的消息的发送状态(更新单条消息)。 * * @param fingerPrint 消息指纹码(消息id) * @param sendStatus 发送状态,see {@link MsgSendStatus} */ updateMessageSendStatus(fingerPrint: string, sendStatus: MsgSendStatus): void { // 遍历消息列表 for(let i = 0; i < this.messages.length; i++) { let m = this.messages[i ]; // 对符合条件的消息对象进行消息发送状态的设置 if(m && m.isOutgoing() && m.fingerPrintOfProtocal === fingerPrint) { // 更新状态 m.sendStatus = sendStatus; // 通知应用层更新ui(参数就是消息所在索引) IMClientManager.getInstance().getEmitter().emit(UIEvent.UIEVENT_messageUpdate, i); } } } /** * 更新指定指纹码的消息的发送状态(更新多条消息)。 * 目前用于QoS送达机制中告诉应用层有哪些原始消息报文未成功送达给对方。 * * @param protocals 原始消息报文对象数组,数组中Protocal对象指纹码(消息id)就是本次要更新的对象,这个数组目前来自于SDK的 EventType.onMessagesLost 事件通知 * @param sendStatus 发送状态,see {@link MsgSendStatus} */ updateMessagesSendStatus(protocals: Protocal[], sendStatus: MsgSendStatus): void { let updateIndexes: number[] = []; // 遍历消息列表 // this.messages.forEach((m: Message) => { for(let mi = 0; mi < this.messages.length; mi++) { let m = this.messages[mi]; for(let i = 0; i < protocals.length; i++){ let p = protocals[i ]; // 对符合条件的消息对象进行消息发送状态的设置 if(m && m.isOutgoing() && m.fingerPrintOfProtocal === p.fp) { // 更新状态 m.sendStatus = sendStatus; // 加入已更新索引列表集合 updateIndexes.push(mi); break; } } } if(updateIndexes.length > 0) { // 通知应用层更新ui(参数就是消息所在索引) IMClientManager.getInstance().getEmitter().emit(UIEvent.UIEVENT_messagesUpdate, updateIndexes); } } /** * 清空所有消息。 */ clear(): void { this.messages = []; } /** * 为当前的消息对象,设置是否显示消息时间标识。 * * 此时间显示逻辑是与微信保持一致的:即只显示5分钟内聊天消息的时间标识,参考资料:[url=http://www.52im.net/thread-3008-1-1.html#40]http://www.52im.net/thread-3008-1-1.html#40[/url] * * @param theMessage 当前消息对象,不可为null * @param previousMessage 当前消息的自然时间的上一条消息,此消息可为空(此为空即表示当前消息就是消息集合中的第一条消息) */ private static setMessageShowTopTime(theMessage: Message, previousMessage: Message | undefined): void { if(theMessage) { if(previousMessage === undefined) { theMessage.showTopTime = true; return; } // 以下代码用于判断并实现仿微信的只显示5分钟内聊天消息的时间标识(参考资料:[url=http://www.52im.net/thread-3008-1-1.html#40]http://www.52im.net/thread-3008-1-1.html#40[/url]) if(theMessage.date - previousMessage.date > MessagesProvider.CHATTING_MESSAGE_SHOW_TIME_INTERVAL) theMessage.showTopTime = true; } } }
/** * 聊天界面(ChatPage.ets)中的List列表对应的数据源实现类(负责聊天消息数据的UI显示)。 * * 注意:本类中的数据来源为全局消息缓存管理类 MessageProvider 中缓存消息集合的对象引用(浅拷贝),相当于共用同一个缓存,无需单 * 独维护数据,实现了聊天消息数据的管理(MessageProvider负责)和UI界面显示(MessagesDataSource负责)的解偶。 * * @author JackJang * @since 1.0 */ export default class MessagesDataSource extends BasicDataSource<Message> { /** 引用全局消息缓存管理类 MessageProvider 中缓存消息集合(浅拷贝)*/ private messages: Array<Message> = IMClientManager.getInstance().getMessageProvider().getMessages(); notifyDataReload(): void { super.notifyDataReload(); } totalCount(): number { return this.messages.length } getData(index: number): Message { return this.messages[index] } /** * 在List中使用LazyForEach时,响应式ui需要key变化才会更新,本方法就是按可变的内容计算key,从而在DataSource更新时, * 能让ui感知到,不然UI是不会刷新显示的。 * * @param m 消息对象 * @returns 计算出的key */ static messageItemKey(m: Message) { // 优化点:给更新的消息对象加个最近更新时间戳,这应该是个更通用的key计算项,不然一旦变更内容多了,这个key的计算就不那么优雅了 return m.msgType + '-' + m.fingerPrintOfProtocal + '-' + m.sendStatus; } }
export default class SocketEvent { /** 网络事件:登录连接或掉线重连响应反馈 */ static readonly SOCKET_EVENT_ON_LOGIN_RESPONSE: string; /** 网络事件:网络断开(掉线了) */ static readonly SOCKET_EVENT_ON_LINK_CLOSE: string; /** 网络事件:收到新的消息 */ static readonly SOCKET_EVENT_ON_RECIEVE_MESSAGE: string; /** 网络事件:服务端反馈的错误信息(这种错误出现即表示连接不可恢复,SDK框架将会自动进入重连动作) */ static readonly SOCKET_EVENT_ON_ERROR_RESPONSE: string; /** 网络事件:发出的消息没有成功被送达(没有收到应答确认包) */ static readonly SOCKET_EVENT_MESSAGE_LOST: string; /** 网络事件:发出的消息已成功被送达(收到应答确认包) */ static readonly SOCKET_EVENT_MESSAGE_BE_RECIEVED: string; /** 网络事件:正在尝试掉线重连动作 */ static readonly SOCKET_EVENT_RECONNECT_ATTEMPT: string; /** 网络事件:心跳包(客户端发出的) */ static readonly SOCKET_EVENT_PING: string; /** 网络事件:心跳包(客户端收到的) */ static readonly SOCKET_EVENT_PONG: string; /** 网络事件:客户端已被强行踢出 */ static readonly SOCKET_EVENT_KICKOUT: string; }
/** * 应用层的各种通知事件类型,这些事件主要用于通知UI界面的更新等。 * * @author Jack Jiang([url=http://www.52im.net/thread-2792-1-1.html]http://www.52im.net/thread-2792-1-1.html[/url]) */ export default class UIEvent { /** UI事件:登录或掉线重连完成 */ static readonly UIEVENT_onIMAfterLoginComplete: string = "uievent.onIMAfterLoginComplete"; /** UI事件:掉线了 */ static readonly UIEVENT_onIMDisconnected: string = "uievent.onIMDisconnected"; /** UI事件:心跳了一次(发出的) */ static readonly UIEVENT_onIMPing: string = "uievent.onIMPing"; /** UI事件:心跳了一次(收到的应答包) */ static readonly UIEVENT_onIMPong: string = "uievent.onIMPong"; /** UI事件:你被踢了 */ static readonly UIEVENT_onKickout: string = "uievent.onKickout"; /** UI事件:增加了聊天消息 */ static readonly UIEVENT_messageAdded = 'uievent.messageAdded'; /** UI事件:更新了聊天消息(单条聊天消息) */ static readonly UIEVENT_messageUpdate = 'uievent.messageUpdate'; /** UI事件:更新了聊天消息(多条聊天消息) */ static readonly UIEVENT_messagesUpdate = 'uievent.messagesUpdate'; }
来源:即时通讯网 - 即时通讯开发者社区!
轻量级开源移动端即时通讯框架。
快速入门 / 性能 / 指南 / 提问
轻量级Web端即时通讯框架。
详细介绍 / 精编源码 / 手册教程
移动端实时音视频框架。
详细介绍 / 性能测试 / 安装体验
基于MobileIMSDK的移动IM系统。
详细介绍 / 产品截图 / 安装体验
一套产品级Web端IM系统。
详细介绍 / 产品截图 / 演示视频
精华主题数超过100个。
连续任职达2年以上的合格正式版主
为论区做出突出贡献的开发者、版主等。
Copyright © 2014-2024 即时通讯网 - 即时通讯开发者社区 / 版本 V4.4
苏州网际时代信息科技有限公司 (苏ICP备16005070号-1)
Processed in 0.127921 second(s), 44 queries , Gzip On.