ChatUtils.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // 格式化时间
  2. export function formatDateTime(date) {
  3. let y = date.getFullYear();
  4. let m = date.getMonth() + 1;
  5. m = m < 10 ? '0' + m : m;
  6. let d = date.getDate();
  7. d = d < 10 ? '0' + d : d;
  8. let h = date.getHours();
  9. h = h < 10 ? '0' + h : h;
  10. let minute = date.getMinutes();
  11. minute = minute < 10 ? '0' + minute : minute;
  12. let second = date.getSeconds();
  13. second = second < 10 ? '0' + second : second;
  14. return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
  15. }
  16. /**
  17. * 毫秒转换友好的显示格式
  18. * 输出格式:21小时前
  19. * @param {[type]} date 日期
  20. */
  21. export function dateStr(date) {
  22. // 获取js 时间戳
  23. let time = new Date().getTime();
  24. // 去掉 js 时间戳后三位
  25. time = parseInt((time - date * 1000) / 1000);
  26. // 存储转换值
  27. let s;
  28. if (time < 60 * 10) {
  29. // 十分钟内
  30. return '刚刚';
  31. } else if (time < 60 * 60 && time >= 60 * 10) {
  32. // 超过十分钟少于1小时
  33. s = Math.floor(time / 60);
  34. return s + '分钟前';
  35. } else if (time < 60 * 60 * 24 && time >= 60 * 60) {
  36. // 超过1小时少于24小时
  37. s = Math.floor(time / 60 / 60);
  38. return s + '小时前';
  39. } else if (time < 60 * 60 * 24 * 3 && time >= 60 * 60 * 24) {
  40. // 超过1天少于3天内
  41. s = Math.floor(time / 60 / 60 / 24);
  42. return s + '天前';
  43. } else {
  44. // 超过3天
  45. var date = new Date(value); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
  46. var Y = date.getFullYear() + '-';
  47. var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
  48. var D = date.getDate() + ' ';
  49. var h = date.getHours() + ':';
  50. var m = date.getMinutes() + ':';
  51. var ss = date.getSeconds();
  52. return h + m + ss;
  53. }
  54. }
  55. /**
  56. * 聊天会话
  57. */
  58. export class Chat {
  59. constructor(id, name, avatar, unReadCount, lastMessage, mobile, email, type) {
  60. this.id = id;
  61. this.name = name;
  62. this.avatar = avatar;
  63. this.unReadCount = unReadCount;
  64. this.lastMessage = lastMessage;
  65. this.mobile = mobile;
  66. this.email = email;
  67. this.type = type;
  68. }
  69. }
  70. /**
  71. * 图片加载完成处理函数
  72. * @param arr 图片的src集合
  73. * @returns {Promise}
  74. */
  75. function preloadImages(arr) {
  76. let loadedImage = 0;
  77. let images = [];
  78. return new Promise(function(resolve, reject) {
  79. for (let i = 0; i < arr.length; i++) {
  80. images[i] = new Image();
  81. images[i].src = arr[i];
  82. images[i].onload = function() {
  83. loadedImage++;
  84. if (loadedImage === arr.length) {
  85. resolve();
  86. }
  87. };
  88. images[i].onerror = function() {
  89. reject();
  90. };
  91. }
  92. });
  93. }
  94. /**
  95. * 图片加载完成,聊天对话框scroll拉到最下
  96. * @param id 容器id
  97. */
  98. export function imageLoad(id) {
  99. scrollBottom(id);
  100. let messageBox = document.getElementById(id);
  101. if (messageBox) {
  102. let images = messageBox.getElementsByTagName('img');
  103. if (images) {
  104. let arr = [];
  105. for (let i = 0; i < images.length; i++) {
  106. arr[i] = images[i].src;
  107. }
  108. preloadImages(arr)
  109. .then(() => {
  110. scrollBottom(id);
  111. })
  112. .catch(function() {
  113. scrollBottom(id);
  114. });
  115. }
  116. }
  117. }
  118. /**
  119. * 滚动条到最下方
  120. * @param id 容器id
  121. */
  122. function scrollBottom(id) {
  123. let div = document.getElementById(id);
  124. if (div) {
  125. div.scrollTop = div.scrollHeight;
  126. }
  127. }
  128. const list = [
  129. "微笑", "撇嘴", "色", "发呆", "得意", "流泪", "害羞", "闭嘴", "睡", "大哭", "尴尬", "发怒", "调皮", "呲牙", "惊讶", "难过", "囧", "抓狂", "吐", "偷笑", "愉快", "白眼", "傲慢", "困", "惊恐", "流汗", "憨笑", "悠闲", "奋斗", "咒骂", "疑问", "嘘", "晕", "衰", "骷髅", "敲打", "再见", "擦汗", "抠鼻", "鼓掌", "坏笑", "左哼哼", "右哼哼", "哈欠", "鄙视", "委屈", "快哭了", "阴险", "亲亲", "可怜", "菜刀", "西瓜", "啤酒", "咖啡", "猪头", "玫瑰", "凋谢", "嘴唇", "爱心", "心碎", "蛋糕", "炸弹", "便便", "月亮", "太阳", "拥抱", "强", "弱", "握手", "胜利", "抱拳", "勾引", "拳头", "OK", "跳跳", "发抖", "怄火", "转圈", "高兴", "口罩", "笑哭", "吐舌头", "傻呆", "恐惧", "悲伤", "不屑", "嘿哈", "捂脸", "奸笑", "机智", "皱眉", "耶", "鬼脸", "合十", "加油", "庆祝", "礼物", "红包", "鸡"
  130. ]
  131. export let faceUtils = {
  132. alt: list.map(item => `[${item}]`),
  133. faces: () => {
  134. let obj = {}
  135. for (let i = 0; i < list.length; i++) {
  136. const key = `[${list[i]}]`
  137. obj[key] = `https://liangxin.zthymaoyi.com/upload/${i}.png`
  138. }
  139. return obj;
  140. }
  141. };
  142. export function transform(content) {
  143. // 支持的html标签
  144. let html = function(end) {
  145. return new RegExp('\\n*\\[' + (end || '') +
  146. '(code|pre|div|span|p|table|thead|th|tbody|tr|td|ul|li|ol|li|dl|dt|dd|h2|h3|h4|h5)([\\s\\S]*?)]\\n*', 'g');
  147. };
  148. let fa = faceUtils.faces();
  149. if (content) {
  150. content = content
  151. .replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;')
  152. .replace(/</g, '&lt;')
  153. .replace(/>/g, '&gt;')
  154. .replace(/'/g, '&#39;')
  155. .replace(/"/g, '&quot;') // XSS
  156. .replace(/@(\S+)(\s+?|$)/g, '@<a href="javascript:;">$1</a>$2')
  157. .replace(/\[([^\s\[\]]+?)]/g, function(face) {
  158. // 转义表情
  159. let alt = face.replace(/^/g, '');
  160. return '<img width="30" alt="' + fa[alt] + '" title="' + fa[alt] + '" src="' + fa[alt] + '">';
  161. })
  162. .replace(/img\[([^\s]+?)]/g, function(img) {
  163. // 转义图片
  164. let href = img.replace(/(^img\[)|(]$)/g, '');
  165. return '<img class="message-img" src="' + href + '" alt="消息图片不能加载">';
  166. })
  167. .replace(/file\([\s\S]+?\)\[[\s\S]*?]/g, function(str) {
  168. // 转义文件
  169. let href = (str.match(/file\(([\s\S]+?)\)\[/) || [])[1];
  170. let text = (str.match(/\)\[([\s\S]*?)]/) || [])[1];
  171. if (!href) return str;
  172. return '<a class="message-file" href="' + href + '"><i class="ivu-icon ivu-icon-md-arrow-down"></i>' + (text ||
  173. href) + '</a>';
  174. })
  175. .replace(/audio\[([^\s]+?)]/g, function(audio) {
  176. // 转义音频
  177. return '<div class="message-audio" data-src="' + audio.replace(/(^audio\[)|(]$)/g, '') +
  178. '"><i class="layui-icon">&#xe652;</i><p>音频消息</p></div>';
  179. })
  180. .replace(/video\[([^\s]+?)]/g, function(video) {
  181. // 转义音频
  182. return '<div class="message-video" data-src="' + video.replace(/(^video\[)|(]$)/g, '') +
  183. '"><i class="layui-icon">&#xe652;</i></div>';
  184. })
  185. .replace(/a\([\s\S]+?\)\[[\s\S]*?]/g, function(str) {
  186. // 转义链接
  187. let href = (str.match(/a\(([\s\S]+?)\)\[/) || [])[1];
  188. let text = (str.match(/\)\[([\s\S]*?)]/) || [])[1];
  189. if (!href) return str;
  190. return '<a href="' + href + '" target="_blank">' + (text || href) + '</a>';
  191. })
  192. .replace(html(), '<$1 $2>')
  193. .replace(html('/'), '</$1>') // 转移HTML代码
  194. .replace(/\n/g, '<br>'); // 转义换行
  195. }
  196. return content;
  197. }
  198. export const ChatListUtils = {
  199. listKey: '_chatList',
  200. setChatList: function(userId, chatList) {
  201. localStorage.setItem(userId + this.listKey, JSON.stringify(chatList));
  202. },
  203. //从缓存中获取已经保存的会话
  204. getChatList: function(userId) {
  205. let str = localStorage.getItem(userId + this.listKey);
  206. if (!str) {
  207. return [];
  208. }
  209. return JSON.parse(str);
  210. },
  211. //删除聊天会话框
  212. delChat: function(userId, chat) {
  213. let tempChatList = [];
  214. for (let item of this.getChatList(userId)) {
  215. if (String(item.id) !== String(chat.id)) {
  216. tempChatList.push(item);
  217. }
  218. }
  219. // 放入缓存
  220. this.setChatList(userId, tempChatList);
  221. return tempChatList;
  222. },
  223. /**
  224. * 刷新会话列表
  225. * @param self 当前对象
  226. * @param user 用户
  227. * @param host 主机名
  228. * @param type 0 单聊 1 群聊
  229. * @returns {Chat} 当前会话
  230. */
  231. resetChatList: function(self, user, host, type) {
  232. console.log('user:' + JSON.stringify(user));
  233. let chatList = this.getChatList(self.$store.state.user.id);
  234. // 删除当前用户已经有的会话
  235. let newChatList = chatList.filter(function(element) {
  236. return String(element.id) !== String(user.id);
  237. });
  238. let avatar = user.avatar;
  239. if (user.avatar.indexOf(host) === 0) {
  240. avatar = user.avatar;
  241. } else {
  242. avatar = host + user.avatar;
  243. }
  244. // 重新添加会话,放到第一个
  245. let chat = new Chat(user.id, user.name, avatar, 0, '', user.mobile, user.email, type);
  246. newChatList.unshift(chat);
  247. // 存储到localStorage 的 chatList
  248. this.setChatList(self.$store.state.user.id, chatList);
  249. self.$store.commit('setChatList', newChatList);
  250. return chat;
  251. }
  252. };
  253. //信息的类型 MSG_PING 心跳 、MSG_READY 链接就绪 MSG_MESSAGE 消息
  254. export const MessageInfoType = {
  255. MSG_PING: '0',
  256. MSG_READY: '1',
  257. MSG_MESSAGE: '2'
  258. };
  259. //信息的目标类型 FRIEND 私聊 、CHAT_GROUP 群聊
  260. export const MessageTargetType = {
  261. FRIEND: '0',
  262. CHAT_GROUP: '1'
  263. };
  264. export const ErrorType = {
  265. TIMEOUT_ERROR: 9, //超时
  266. TOKEN_ERROR: 401, //token 失效错误
  267. PARAM_ERROR: 400, //参数错误
  268. FLUSH_TOKEN_ERROR: 7, //刷新token错误
  269. SERVER_ERROR: 500, //服务器错误
  270. NET_ERROR: 'TypeError: Failed to fetch' //网络链接不通
  271. };