123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636 |
- import { MessageBox } from 'element-ui'
- import TWEEN from '@tweenjs/tween.js'
- import twemoji from 'twemoji'
- import dayjs from 'dayjs'
- const timestampInterval = 1e3 * 60 * 3 // 3分钟的间隔时间
- const cryptoKey = 'dqWt6twz6JyEy3EZ'
- export function isDev () {
- return /^test|\.webdev2\./.test(window.location.host) || window.location.port !== ''
- }
- // 错误弹窗
- export function showError (msg, title = 'Error') {
- MessageBox.confirm(msg, title, {
- center: true,
- showCancelButton: false,
- showConfirmButton: false,
- callback () {}
- })
- }
- // 确认操作弹窗
- export function confirmPopup (msg, title = '提示') {
- return new Promise((resolve, reject) => {
- MessageBox.confirm(msg, '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- })
- .then(() => {
- resolve()
- })
- .catch(() => {})
- })
- }
- /**
- * 判断系统||浏览器中英文
- * 对于不支持的浏览器 一律默认为 中文
- */
- export function getLanguage () {
- var language = (navigator.language || navigator.browserLanguage).toLowerCase()
- var locale = 'zh'
- if (language.indexOf('en') > -1) {
- locale = 'en'
- } else {
- locale = 'zh'
- }
- return locale
- }
- /**
- * 获取Url上指定参数
- * @param {String} name 参数名
- */
- export function getUrlParam (name) {
- var reg = new RegExp('[?&]' + name + '=([^&#?]*)(&|#|$)')
- var r = window.location.href.match(reg)
- return r ? r[1] : null
- }
- export var Cookie = {
- setCookie (name, value) {
- var Days = 7
- var exp = new Date()
- exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000)
- exp.setTime(exp.getTime() + 60 * 1000)
- if (
- window.location.port === '8080' ||
- /^test-|\.webdev2\./.test(window.location.host)
- ) {
- document.cookie =
- name + '=' + escape(value) + ';expires=' + exp.toGMTString()
- } else {
- document.cookie =
- name +
- '=' +
- escape(value) +
- ';domain=.mee.chat;path=/;expires=' +
- exp.toGMTString()
- }
- },
- getCookie (name) {
- var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
- var arr = document.cookie.match(reg)
- if (arr) {
- return unescape(arr[2])
- } else {
- return null
- }
- },
- delCookie (name) {
- var str1 = name + '=;domain=.mee.chat;path=/'
- str1 += ';expires=' + new Date(0).toGMTString()
- document.cookie = str1
- var str2 = name + '=;path=/'
- str2 += ';expires=' + new Date(0).toGMTString()
- document.cookie = str2
- }
- }
- /**
- * 获取聊天区域高度
- * @param {String} msg
- */
- export function getResizeHeight () {
- let clientHeight = document.documentElement.clientHeight
- let clientWidth = document.documentElement.clientWidth
- let topHeight = 61
- let botHeight = 181
- var chatBoxHeight
- if (clientHeight < 600) {
- chatBoxHeight = 600 - topHeight - botHeight
- }
- if (clientHeight < 800 || clientWidth < 1000) {
- chatBoxHeight = clientHeight - topHeight - botHeight
- } else {
- chatBoxHeight = clientHeight * 0.8 - topHeight - botHeight
- }
- return chatBoxHeight
- }
- function rc4 (str, key) {
- var s = []
- var j = 0
- var x
- var res = ''
- for (var i = 0; i < 256; i++) {
- s[i] = i
- }
- for (i = 0; i < 256; i++) {
- j = (j + s[i] + key.charCodeAt(i % key.length)) % 256
- x = s[i]
- s[i] = s[j]
- s[j] = x
- }
- i = 0
- j = 0
- for (var y = 0; y < str.length; y++) {
- i = (i + 1) % 256
- j = (j + s[i]) % 256
- x = s[i]
- s[i] = s[j]
- s[j] = x
- res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256])
- }
- return res
- }
- /**
- * 加密信息
- * @param {String} msg
- */
- export function cryptoMsg (msg) {
- let result
- try {
- result = btoa(rc4(encodeURIComponent(msg), cryptoKey))
- } catch {
- return msg
- }
- return result
- }
- /**
- * 解密信息
- * @param {String} msg
- */
- export function decryptoMsg (msg) {
- let result
- try {
- result = decodeURIComponent(rc4(atob(msg), cryptoKey))
- } catch {
- return msg
- }
- return result
- }
- const linkRule = new RegExp(
- '(https?|ftp|file)://[-a-zA-Z0-9/-_.?#!+%&]+'
- )
- /**
- * 向数组添加数据
- * @param {Array} data
- */
- export function addSomeInArray (data) {
- let lastTime = null
- data.forEach(item => {
- // 添加timeMsg tag
- if (lastTime === null) {
- item.timeMsg = false
- } else {
- item.timeMsg = parseInt(item.timestamp) - lastTime > timestampInterval
- }
- lastTime = parseInt(item.timestamp)
- addLinkItem(item)
- })
- }
- /**
- * 单个添加timeMsg tag
- * @param {Array} data
- */
- export function addTimeMsgInItem (item, arr) {
- if (arr.length === 0) {
- item.timeMsg = true
- } else {
- let lastTime = parseInt(arr[arr.length - 1].timestamp)
- item.timeMsg = parseInt(item.timestamp) - lastTime > timestampInterval
- }
- }
- /**
- * 判断是否是移动端
- */
- export function isMobile () {
- return /Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)
- }
- /**
- * 获得meechat版本
- * */
- export function getMeechatType () {
- if (location.pathname.indexOf('mini') > -1) {
- return 'mini'
- } else if (isMobile()) {
- return 'h5'
- } else {
- return 'pc'
- }
- }
- function convertEntity (str) {
- // :)
- const entityMap = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": '''
- }
- return str.replace(/[&<>'"]/g, function (matched) {
- return entityMap[matched]
- })
- }
- /*
- * 单个添加链接 msg_type = 10
- * @param {Array} data
- */
- export function addLinkItem (item) {
- // 先用实体处理
- if (item.msg_type == 0) {
- item.content = convertEntity(item.content)
- if (item.content.match(linkRule)) {
- item.content = item.content.replace(linkRule, a => {
- return `<a href="${a}" class="link text" target="_blank">${a}</a>`
- })
- }
- item.content = twemoji.parse(item.content, {
- callback: function (icon, options) {
- return 'https://w2.meechat.me/emoji/' + icon + '.svg'
- }
- })
- }
- }
- /**
- * 移除arr2中满足callback的arr1数组元素
- * @param {Array} arr1 [{hash:1}]
- * @param {Array} arr2 [{hash:1},{hash:2}]
- * @result arr1 => []
- */
- export function removeItemIfEixt (arr1, arr2, callback) {
- arr1.forEach((item, index) => {
- if (arr2.some(item2 => callback(item2) == callback(item))) {
- arr1.splice(index, 1)
- }
- })
- }
- /**
- * 格式化置顶消息
- */
- export function formatPinMsg (pinMsg, userId) {
- pinMsg.name = pinMsg.nick_name
- pinMsg.content = decryptoMsg(pinMsg.msg)
- pinMsg.type = pinMsg.from == userId ? 'me' : 'you'
- pinMsg.avatar = pinMsg.cover_photo || ''
- pinMsg.userId = pinMsg.from
- }
- /**
- * @param {store} state
- * @param {Number} createTime
- */
- export function dealErrorMsg (state, createTime) {
- state.chatList.forEach(item => {
- if (item.createTime == createTime) {
- item.fail = true
- item.loading = false
- }
- })
- }
- /**
- * 如果含有at他人的信息,格式化
- * @param {String} msg @heitan@aben 123
- * @param {Array} members
- * @result => {@start[10,9]end}@heitan@aben 123
- */
- export function encryptAtMsg (msg, members) {
- let ats = []
- members.forEach(user => {
- let reg = new RegExp(`@${user.nick_name}`)
- if (reg.test(msg)) {
- ats.push(user.user_id)
- }
- })
- if (ats.length) {
- msg = `{@start[${ats.toString()}]end}${msg}`
- }
- return msg
- }
- /**
- *
- * @param {String} msg
- * @return {Array|Null}
- */
- export function decryptAtMsg (msg) {
- let reg = /^{@start\[(.*)\]end}/
- let ret = reg.exec(msg)
- if (ret) {
- return ret[0].split(',')
- }
- }
- /**
- *判断是否是at我的信息
- */
- export function checkAtMe (msg, username) {
- if (!username) return false
- let reg = new RegExp(`@${username}`)
- return reg.test(msg)
- }
- export function scrollIntoView (node, offsetTop) {
- let distance = Math.abs(offsetTop - node.scrollTop)
- let time = distance > 500 ? 1000 : distance * 2
- let tw = new TWEEN.Tween(node)
- .to({ scrollTop: offsetTop }, time)
- .easing(TWEEN.Easing.Quadratic.Out)
- return tw.start()
- }
- export function scrollMsgIntoView (node, offsetTop, targetNode, callback) {
- scrollIntoView(node, offsetTop)
- .onComplete(() => {
- targetNode.classList.toggle('active')
- callback && callback()
- })
- setTimeout(() => {
- targetNode.classList.toggle('active')
- }, 3000)
- }
- export var noticeManager = {
- tabTimer: null, // tab切换定时器
- askPermission () {
- return new Promise((resolve, reject) => {
- if (!('Notification' in window)) {
- reject(new Error('This browser does not support desktop notification'))
- } else if (Notification.permission === 'granted') {
- resolve()
- } else if (Notification.permission === 'default ') {
- Notification.requestPermission(function (permission) {
- // 如果用户同意,就可以向他们发送通知
- if (permission === 'granted') {
- resolve()
- } else {
- reject(new Error())
- }
- })
- }
- })
- },
- showNotification (data) {
- // 开启全局消息免扰
- if (this.getGlobalNotice() == 1) return
- // 已经打开页面了,就不需要额外通知
- let userId = localStorage.getItem('user_id')
- // 自己发的消息不用通知
- if (userId == data.from) return
- this.askPermission().then(() => {
- let notification = new Notification(data.name, {
- body: '你收到了一条消息',
- icon: `/dist/img/icons/meechat.png`
- })
- // 打开页面
- let path
- if (data.group_id) {
- path = `/group/${data.group_id}`
- } else {
- let sessionId = +data.to > +data.from ? `${data.from}-${data.to}` : `${data.to}-${data.from}`
- path = `/pm/${sessionId}`
- }
- notification.onclick = () => {
- window.$router.push({ path })
- notification.close()
- window.focus()
- }
- setTimeout(() => {
- notification.close()
- }, 3500)
- })
- },
- changeTitle (num) {
- // 开启全局消息免扰
- // if (this.getGlobalNotice() == 1) return
- let title = num ? `${num}条新消息 - MeeChat` : `MeeChat`
- document.title = title
- if (num) {
- num = num > 99 ? '99+' : num
- if (this.tabTimer) clearTimeout(this.tabTimer)
- }
- },
- getGlobalNotice () {
- if (window.Notification && Notification.permission === 'granted') {
- // getUserOpt('mute')
- // let systemConfig = JSON.parse(localStorage.getItem('systemConfig') || '{}')
- // let mute = getUserOpt('mute')
- // return typeof systemConfig.mute === 'undefined' ? 1 : systemConfig.mute
- let mute = getUserOpt('mute')
- return mute || 0
- } else {
- return 1
- }
- },
- /**
- * @des 设置通知提醒
- * @param type {0:开启,1:关闭}
- * */
- setGlobalNotice (type, that) {
- // let systemConfig = JSON.parse(localStorage.getItem('systemConfig') || '{}')
- if (type == 0) {
- Notification.requestPermission(function (permission) {
- // 如果用户同意,就可以向他们发送通知
- let mute = permission === 'granted' ? 0 : 1
- that.openGlobalNotice = mute
- setUserOpt('mute', mute)
- })
- } else {
- that.openGlobalNotice = type
- setUserOpt('mute', type)
- }
- }
- }
- /**
- * @des 转换消息时间
- * @param {timeStamp} 时间戳
- * @param {type} 类型{1:会话列表,2:信息段}
- */
- export function formatMsgTime (timeStamp, type = 1, that) {
- if (!timeStamp) return ''
- let lastDate = dayjs().subtract(1, 'days').format('YYYY-MM-DD') // 昨天
- let inputDay = dayjs(timeStamp * 1)
- let inputDate = inputDay.format('YYYY-MM-DD')
- switch (type) {
- // 会话列表
- case 1:
- if (inputDate < lastDate) {
- return inputDay.format('MM-DD')
- } else if (lastDate == inputDate) {
- return that.$t('chat.yesterday')
- } else {
- return inputDay.format('HH:mm')
- }
- // 信息段
- case 2:
- if (inputDate < lastDate) {
- return inputDay.format('MM-DD HH:mm')
- } else if (lastDate == inputDate) {
- return that.$t('chat.yesterday') + ` ${inputDay.format('HH:mm')}`
- } else {
- return inputDay.format('HH:mm')
- }
- }
- }
- /**
- * @des 跳去h5登录页
- * */
- export function toLoginPage () {
- let url = encodeURIComponent(location.hash.replace('#', ''))
- location.replace(`${location.origin + location.pathname}#/login?from=${url}`)
- // rounter.replace(`/login?from=${url}`)
- }
- /**
- * @des 将图片地址转成base64
- */
- export function getBase64 (imgUrl, callback) {
- window.URL = window.URL || window.webkitURL
- var xhr = new XMLHttpRequest()
- xhr.open('get', imgUrl, true)
- // 至关重要
- xhr.responseType = 'blob'
- xhr.onload = function () {
- if (this.status == 200) {
- // 得到一个blob对象
- var blob = this.response
- // 至关重要
- let oFileReader = new FileReader()
- oFileReader.onloadend = function (e) {
- let base64 = e.target.result
- callback && callback(base64)
- }
- oFileReader.readAsDataURL(blob)
- }
- }
- xhr.send()
- }
- /**
- * @des 图片懒加载
- * @param {el} wrap 图片容器
- * @param {HTMLCollection} imageArr 图片列表
- * @param {String} derection 整体列表滑动方向['down','up']
- */
- export function lazyloadImage ({ wrap, imageArr, derection = 'down' }) {
- if (!imageArr || imageArr.length <= 0) return
- let imageLen = imageArr.length
- let listScrollTop = wrap.scrollTop
- let listClientHeight = wrap.clientHeight
- switch (derection) {
- case 'down':
- for (let i = 0; i < imageLen; i++) {
- let item = imageArr[i]
- let originUrl = item.getAttribute('originurl')
- let url = item.getAttribute('src')
- if (item.offsetTop - listScrollTop <= listClientHeight) {
- if (originUrl && originUrl != url) item.setAttribute('src', originUrl)
- } else {
- return i >= 1 ? i - 1 : 0
- }
- }
- break
- case 'up':
- for (let i = imageLen - 1; i >= 0; i--) {
- let item = imageArr[i]
- let originUrl = item.getAttribute('originurl')
- let url = item.getAttribute('src')
- let top = item.getBoundingClientRect().top
- if (top >= -100 && top < listClientHeight + 300) {
- if (originUrl && originUrl != url) item.setAttribute('src', originUrl)
- }
- }
- break
- }
- }
- /**
- * @des 获取头像背景色
- * @param {*} str 房间号
- * @param {*} userId 当前用户id
- */
- export function getAvatarBgColor (str, userId) {
- str += ''
- if (str.match('-')) {
- let num = 0
- str.split('-').forEach(e => {
- if (e !== userId) {
- num = e % 9
- }
- })
- return num + ''
- } else {
- return str % 9 + ''
- }
- }
- /**
- * @des 打开一个空白窗口
- * @param {String} url 链接
- * @param {Number} iWidth 弹出窗口的宽度
- * @param {Number} iHeight 弹出窗口的高度
- */
- export function openBlankWindow (url = '', iWidth = 500, iHeight = 600) {
- var iTop = (window.screen.availHeight - 30 - iHeight) / 2 // 获得窗口的垂直位置;
- var iLeft = (window.screen.availWidth - 10 - iWidth) / 2 // 获得窗口的水平位置;
- var winHandler = window.open(url, '_blank', 'height=' + iHeight + ', width=' + iWidth + ', top=' + iTop + ', left=' + iLeft + ', toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no')
- return winHandler
- }
- /**
- * @des 本地存储用户操作
- * [{'loginType':'登录类型'},{'lang':'语言'}]
- */
- export function getUserOpt (key) {
- let userOpt = localStorage.getItem('userOpt') || '{}'
- userOpt = JSON.parse(userOpt)
- return userOpt[key] || ''
- }
- export function setUserOpt (key, val) {
- let userOpt = localStorage.getItem('userOpt') || '{}'
- userOpt = JSON.parse(userOpt)
- userOpt[key] = val
- localStorage.setItem('userOpt', JSON.stringify(userOpt))
- }
|