util.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. import { MessageBox } from 'element-ui'
  2. import TWEEN from '@tweenjs/tween.js'
  3. const timestampInterval = 1e3 * 60 * 3 // 3分钟的间隔时间
  4. const cryptoKey = 'dqWt6twz6JyEy3EZ'
  5. // 错误弹窗
  6. export function showError (msg, title = 'Error') {
  7. MessageBox.confirm(msg, title, {
  8. center: true,
  9. showCancelButton: false,
  10. showConfirmButton: false,
  11. callback () {}
  12. })
  13. }
  14. // 确认操作弹窗
  15. export function confirmPopup (msg, title = '提示') {
  16. return new Promise((resolve, reject) => {
  17. MessageBox.confirm(msg, '提示', {
  18. confirmButtonText: '确定',
  19. cancelButtonText: '取消',
  20. type: 'warning'
  21. })
  22. .then(() => {
  23. resolve()
  24. })
  25. .catch(() => {})
  26. })
  27. }
  28. /**
  29. * 判断系统||浏览器中英文
  30. * 对于不支持的浏览器 一律默认为 中文
  31. */
  32. export function getLanguage () {
  33. var language = (navigator.language || navigator.browserLanguage).toLowerCase()
  34. var locale = 'zh'
  35. if (language.indexOf('en') > -1) {
  36. locale = 'en'
  37. } else {
  38. locale = 'zh'
  39. }
  40. return locale
  41. }
  42. /**
  43. * 获取Url上指定参数
  44. * @param {String} name 参数名
  45. */
  46. export function getUrlParam (name) {
  47. var reg = new RegExp('[?&]' + name + '=([^&#?]*)(&|#|$)')
  48. var r = window.location.href.match(reg)
  49. return r ? r[1] : null
  50. }
  51. export var Cookie = {
  52. setCookie (name, value) {
  53. var Days = 7
  54. var exp = new Date()
  55. exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000)
  56. exp.setTime(exp.getTime() + 60 * 1000)
  57. if (
  58. window.location.port === '8080' ||
  59. /^test-|\.webdev2\./.test(window.location.host)
  60. ) {
  61. document.cookie =
  62. name + '=' + escape(value) + ';expires=' + exp.toGMTString()
  63. } else {
  64. document.cookie =
  65. name +
  66. '=' +
  67. escape(value) +
  68. ';domain=.mee.chat;path=/;expires=' +
  69. exp.toGMTString()
  70. }
  71. },
  72. getCookie (name) {
  73. var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
  74. var arr = document.cookie.match(reg)
  75. if (arr) {
  76. return unescape(arr[2])
  77. } else {
  78. return null
  79. }
  80. },
  81. delCookie (name) {
  82. var str1 = name + '=;domain=.mee.chat;path=/'
  83. str1 += ';expires=' + new Date(0).toGMTString()
  84. document.cookie = str1
  85. var str2 = name + '=;path=/'
  86. str2 += ';expires=' + new Date(0).toGMTString()
  87. document.cookie = str2
  88. }
  89. }
  90. /**
  91. * 获取聊天区域高度
  92. * @param {String} msg
  93. */
  94. export function getResizeHeight () {
  95. let clientHeight = document.documentElement.clientHeight
  96. let clientWidth = document.documentElement.clientWidth
  97. let topHeight = 61
  98. let botHeight = 181
  99. var chatBoxHeight
  100. if (clientHeight < 600) {
  101. chatBoxHeight = 600 - topHeight - botHeight
  102. }
  103. if (clientHeight < 800 || clientWidth < 1000) {
  104. chatBoxHeight = clientHeight - topHeight - botHeight
  105. } else {
  106. chatBoxHeight = clientHeight * 0.8 - topHeight - botHeight
  107. }
  108. return chatBoxHeight
  109. }
  110. function rc4 (str, key) {
  111. var s = []
  112. var j = 0
  113. var x
  114. var res = ''
  115. for (var i = 0; i < 256; i++) {
  116. s[i] = i
  117. }
  118. for (i = 0; i < 256; i++) {
  119. j = (j + s[i] + key.charCodeAt(i % key.length)) % 256
  120. x = s[i]
  121. s[i] = s[j]
  122. s[j] = x
  123. }
  124. i = 0
  125. j = 0
  126. for (var y = 0; y < str.length; y++) {
  127. i = (i + 1) % 256
  128. j = (j + s[i]) % 256
  129. x = s[i]
  130. s[i] = s[j]
  131. s[j] = x
  132. res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256])
  133. }
  134. return res
  135. }
  136. /**
  137. * 加密信息
  138. * @param {String} msg
  139. */
  140. export function cryptoMsg (msg) {
  141. let result
  142. try {
  143. result = btoa(rc4(encodeURIComponent(msg), cryptoKey))
  144. } catch {
  145. return msg
  146. }
  147. return result
  148. }
  149. /**
  150. * 解密信息
  151. * @param {String} msg
  152. */
  153. export function decryptoMsg (msg) {
  154. let result
  155. try {
  156. result = decodeURIComponent(rc4(atob(msg), cryptoKey))
  157. } catch {
  158. return msg
  159. }
  160. return result
  161. }
  162. /**
  163. * 向数组添加数据
  164. * @param {Array} data
  165. */
  166. export function addSomeInArray (data) {
  167. let lastTime = null
  168. let linkRule = new RegExp(
  169. '(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]'
  170. )
  171. let queLink = /(['"])(?:(?!\1).)*?\1/
  172. data.forEach(item => {
  173. // 添加timeMsg tag
  174. if (lastTime === null) {
  175. item.timeMsg = false
  176. } else {
  177. item.timeMsg = parseInt(item.timestamp) - lastTime > timestampInterval
  178. }
  179. lastTime = parseInt(item.timestamp)
  180. // 添加链接标识 msg_type = 10
  181. if (item.content && typeof item.content == 'string' && !item.content.match(queLink) &&
  182. item.content.match(linkRule) && item.msg_type == 0) {
  183. item.msg_type = 10
  184. item.content = item.content.replace(linkRule, a => {
  185. return `<a href="${a}" class="link text" target="_blank">${a}</a>`
  186. })
  187. }
  188. })
  189. }
  190. /**
  191. * 单个添加timeMsg tag
  192. * @param {Array} data
  193. */
  194. export function addTimeMsgInItem (item, arr) {
  195. if (arr.length === 0) {
  196. item.timeMsg = true
  197. } else {
  198. let lastTime = parseInt(arr[arr.length - 1].timestamp)
  199. item.timeMsg = parseInt(item.timestamp) - lastTime > timestampInterval
  200. }
  201. }
  202. /**
  203. * 判断是否是移动端
  204. */
  205. export function isMobile () {
  206. return /Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)
  207. }
  208. /*
  209. * 单个添加链接 msg_type = 10
  210. * @param {Array} data
  211. */
  212. export function addLinkItem (item) {
  213. var linkRule = new RegExp(
  214. '(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]'
  215. )
  216. var queLink = /(['"])(?:(?!\1).)*?\1/
  217. if (item.content.match(linkRule) && item.msg_type == 0 && !item.content.match(queLink)) {
  218. item.msg_type = 10
  219. item.content = item.content.replace(linkRule, a => {
  220. return `<a href="${a}" class="link text" target="_blank">${a}</a>`
  221. })
  222. }
  223. }
  224. /**
  225. * 移除arr2中满足callback的arr1数组元素
  226. * @param {Array} arr1 [{hash:1}]
  227. * @param {Array} arr2 [{hash:1},{hash:2}]
  228. * @result arr1 => []
  229. */
  230. export function removeItemIfEixt (arr1, arr2, callback) {
  231. arr1.forEach((item, index) => {
  232. if (arr2.some(item2 => callback(item2) == callback(item))) {
  233. arr1.splice(index, 1)
  234. }
  235. })
  236. }
  237. /**
  238. * 格式化置顶消息
  239. */
  240. export function formatPinMsg (pinMsg, userId) {
  241. pinMsg.name = pinMsg.nick_name
  242. pinMsg.content = decryptoMsg(pinMsg.msg)
  243. pinMsg.type = pinMsg.from == userId ? 'me' : 'you'
  244. pinMsg.avatar = pinMsg.cover_photo || ''
  245. pinMsg.userId = userId
  246. }
  247. /**
  248. * @param {store} state
  249. * @param {Number} createTime
  250. */
  251. export function dealErrorMsg (state, createTime) {
  252. state.chatList.forEach(item => {
  253. if (item.createTime == createTime) {
  254. item.fail = true
  255. item.loading = false
  256. }
  257. })
  258. }
  259. /**
  260. * 如果含有at他人的信息,格式化
  261. * @param {String} msg @heitan@aben 123
  262. * @param {Array} members
  263. * @result => {@start[10,9]end}@heitan@aben 123
  264. */
  265. export function encryptAtMsg (msg, members) {
  266. let ats = []
  267. members.forEach(user => {
  268. let reg = new RegExp(`@${user.nick_name}`)
  269. if (reg.test(msg)) {
  270. ats.push(user.user_id)
  271. }
  272. })
  273. if (ats.length) {
  274. msg = `{@start[${ats.toString()}]end}${msg}`
  275. }
  276. return msg
  277. }
  278. /**
  279. *
  280. * @param {String} msg
  281. * @return {Array|Null}
  282. */
  283. export function decryptAtMsg (msg) {
  284. let reg = /^{@start\[(.*)\]end}/
  285. let ret = reg.exec(msg)
  286. if (ret) {
  287. return ret[0].split(',')
  288. }
  289. }
  290. /**
  291. *判断是否是at我的信息
  292. */
  293. export function checkAtMe (msg, username) {
  294. if (!username) return false
  295. let reg = new RegExp(`@${username}`)
  296. return reg.test(msg)
  297. }
  298. export function scrollIntoView (node, offsetTop) {
  299. let distance = Math.abs(offsetTop - node.scrollTop)
  300. let time = distance > 500 ? 1000 : distance * 2
  301. let tw = new TWEEN.Tween(node)
  302. .to({ scrollTop: offsetTop }, time)
  303. .easing(TWEEN.Easing.Quadratic.Out)
  304. return tw.start()
  305. }
  306. export function scrollMsgIntoView (node, offsetTop, targetNode) {
  307. scrollIntoView(node, offsetTop)
  308. .onComplete(() => {
  309. targetNode.classList.toggle('active')
  310. })
  311. setTimeout(() => {
  312. targetNode.classList.toggle('active')
  313. }, 3000)
  314. }
  315. export var noticeManager = {
  316. askPermission () {
  317. return new Promise((resolve, reject) => {
  318. if (!('Notification' in window)) {
  319. reject(new Error('This browser does not support desktop notification'))
  320. } else if (Notification.permission === 'granted') {
  321. resolve()
  322. } else if (Notification.permission === 'default ') {
  323. Notification.requestPermission(function (permission) {
  324. // 如果用户同意,就可以向他们发送通知
  325. if (permission === 'granted') {
  326. resolve()
  327. } else {
  328. reject(new Error())
  329. }
  330. })
  331. }
  332. })
  333. },
  334. showNotification (data) {
  335. this.askPermission().then(() => {
  336. let notification = new Notification(data.name, {
  337. body: '你收到了一条消息',
  338. icon: `${process.env.BASE_URL}icon_192.png`
  339. })
  340. // 打开页面
  341. let path
  342. if (data.group_id) {
  343. path = `/group/${data.group_id}`
  344. } else {
  345. let sessionId = +data.to > +data.from ? `${data.from}-${data.to}` : `${data.to}-${data.from}`
  346. path = `/pm/${sessionId}`
  347. }
  348. notification.onclick = () => {
  349. window.$router.push({ path })
  350. notification.close()
  351. window.focus()
  352. }
  353. setTimeout(() => {
  354. notification.close()
  355. }, 3500)
  356. })
  357. },
  358. changeTitle () {
  359. if (document.hidden) {
  360. document.title = 'MeeChat (你有新消息)'
  361. }
  362. }
  363. }