import api from '@/api' import { getLanguage, getUserOpt, setUserOpt, mobileInputBlur } from '@/util/util' import { mapState } from 'vuex' import _ from 'lodash' // 搜索mixin export const searchUserMixin = { data () { return { isSearch: false, // 搜索展示 searchList: null // 搜索结果 } }, methods: { searchUser (e, originList) { let val = e.target.value.toLocaleLowerCase() if (!val) { this.isSearch = false return } this.searchList = originList.filter(item => { let inName, inNick let name = (item.name || item.user_name || '').toLocaleLowerCase() let nickName = (item.nick_name || '').toLocaleLowerCase() inName = name ? name.indexOf(val) > -1 : false inNick = nickName ? nickName.indexOf(val) > -1 : false return inName || inNick }) this.isSearch = true } } } // 群搜索mixin export const searchGroupUserMixin = { data () { return { showNum: 0, isSearchGroup: false, searchUserTimer: null, searchGroupList: [] } }, methods: { async searchUser (e, originList) { if (!e) return clearTimeout(this.searchUserTimer) this.searchUserTimer = setTimeout(async () => { let val = e.target.value.toLocaleLowerCase() let inviteType = this.inviteType this.isSearchGroup = true if (!val.trim()) { originList.forEach(item => { this.$set(item, 'isShow', true) }) this.$nextTick(() => { this.isSearchGroup = false this.showNum = originList.length originList = this.originListCache }) return } // 当前数据搜索 originList.forEach(item => { let inName, inNick let name = (item.user_name || '').toLocaleLowerCase() let nickName = (item.nick_name || '').toLocaleLowerCase() inName = name ? name.indexOf(val) > -1 : false inNick = nickName ? nickName.indexOf(val) > -1 : false this.$set(item, 'isShow', inName || inNick) }) // 接口搜索 if (!(originList.length + 1 >= this.membersNum || inviteType == 1 || inviteType == 2)) { await api.group.searchMember({ group_id: this.group.groupId, keyword: val }).then(({ data }) => { let list = data.data list.forEach(item => { item.isChecked = false item.isChoosed = false item.isShow = true }) originList = _.unionBy([...originList, ...list], 'user_id') }) } this.searchGroupList = originList this.$nextTick(() => { this.showNum = originList.filter(item => { return item.isShow }).length }) }, 200) } } } // @人 export const chatAtMixin = { data () { return { atInd: 0 // @人索引 } }, methods: { atPerson (name, nickName = name) { let el = this.$refs.chatInput let selectionStart = el.selectionStart let realStart = selectionStart - this.keyAfterAt.length this.inputMsg = this.inputMsg.slice(0, realStart) + `${name} ` + this.inputMsg.slice(selectionStart) this.atInd = 0 el.focus() this.$nextTick(() => { el.setSelectionRange(realStart + name.length + 1, realStart + name.length + 1) }) this.$store.commit('updateIsNewAt', { isNewAt: this.group.isNewAt, isNewAtFound: true }) this.$store.commit('updateGroupSearchList', []) }, handleUp (event) { if (this.atInd > 0) { this.atInd-- } this.atShow && event.preventDefault() return true }, handleDown (event) { let membersLen = this.filterMembers.length this.atInd < membersLen - 1 ? this.atInd++ : this.atInd = 0 this.atShow && event.preventDefault() return true } } } // 聊天输入框 export const chatInputMixin = { data () { return { selectionAfterAt: false, // 光标在@后面 keyAfterAt: '', // 光标后的搜索字 keyAfterAtTimer: '', // 光标后的搜索字触发定时器 lastKeyAfterAt: '', isIOS: !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), isShowContextmenu: false, menuTop: 0, // 右键菜单-top menuLeft: 0 // 右键菜单-left } }, mounted () { }, computed: { ...mapState([ 'copyText' ]), filterMembers () { if (!this.group.groupId) return [] let members = this.group.membersArray let resArr = [] if (this.keyAfterAt !== '') { resArr = this.group.searchList } else { for (let k = 0; k < members.length; k++) { if (members[k].user_id == this.userId) continue resArr.push(members[k]) } } return resArr.slice(0, 100) }, atShow () { this.atInd = 0 return this.selectionAfterAt && this.filterMembers.length } }, watch: { keyAfterAt (val) { clearTimeout(this.keyAfterAtTimer) this.keyAfterAtTimer = setTimeout(() => { this.handleKeyAfterAt(val) }, 200) }, inputMsg (val, newval) { this.handleSelectionChange() } }, methods: { handleKeyAfterAt (val) { if (!this.group.groupId || val.trim() == '') return if (this.group.isNewAtFound) return if (this.group.membersArray.length < this.group.membersNum) { api.group.searchMember({ group_id: this.group.groupId, keyword: val }).then(({ data }) => { this.$store.commit('updateGroupSearchList', data.data) }) } else { let searchList = this.group.membersArray.filter(item => { let inName, inNick inName = item.user_name ? item.user_name.indexOf(val) > -1 : false inNick = item.nick_name ? item.nick_name.indexOf(val) > -1 : false return inName || inNick }) this.$store.commit('updateGroupSearchList', searchList) } }, getStrBeforeSelection () { let el = this.$refs.chatInput if (!el) return '' let selectionStart = el.selectionStart let prevStr = this.inputMsg.slice(0, selectionStart) return prevStr }, getStrAfterSelection () { let el = this.$refs.chatInput if (!el) return '' let selectionStart = el.selectionStart let prevStr = this.inputMsg.slice(selectionStart) return prevStr }, handleClick () { this.isShowContextmenu = false }, handleLeft (event) { let el = this.$refs.chatInput let selectionStart = el.selectionStart if (selectionStart === 0) return true let prevStr = this.getStrBeforeSelection() let members = this.group.members for (let k in members) { let name = members[k].user_name let reg = new RegExp(`@${name} $`) if (reg.test(prevStr)) { event.preventDefault() el.setSelectionRange(selectionStart - name.length - 2, selectionStart - name.length - 2) return true } } }, handleRight (event) { let el = this.$refs.chatInput let selectionStart = el.selectionStart let afterStr = this.getStrAfterSelection() let members = this.group.members for (let k in members) { let name = members[k].user_name let reg = new RegExp(`^@${name} `) if (reg.test(afterStr)) { event.preventDefault() el.setSelectionRange(selectionStart + name.length + 2, selectionStart + name.length + 2) return true } } return true }, handleDel (event) { let el = this.$refs.chatInput let selectionStart = el.selectionStart if (selectionStart === 0) return let prevStr = this.getStrBeforeSelection() let members = this.group.members for (let k in members) { let name = members[k].user_name let reg = new RegExp(`@${name} $`) if (reg.test(prevStr)) { event.preventDefault() this.inputMsg = this.inputMsg.slice(0, selectionStart - name.length - 2) + this.inputMsg.slice(selectionStart) this.$nextTick(() => { el.setSelectionRange(selectionStart - name.length - 2, selectionStart - name.length - 2) }) return } } }, handleKeyDown (event) { if (this.atShow) { event.preventDefault() let item = this.filterMembers[this.atInd] this.atPerson(item.user_name, item.nick_name) return } if (event.altKey || event.ctrlKey) { let beforeStr = this.getStrBeforeSelection() let afterStr = this.getStrAfterSelection() // 单纯换行 this.inputMsg = beforeStr + '\n' + afterStr this.$nextTick(() => { this.$refs.chatInput.setSelectionRange(beforeStr.length + 1, beforeStr.length + 1) }) } else { this.handleSend(event) event.preventDefault() } return true }, handleFocus () { this.$emit('handleFocus') // 针对完整版 this.updateChatInputFocus(true) document.addEventListener('selectionchange', this.handleSelectionChange) if (this.isIOS) { setTimeout(() => { this.$root.$el.addEventListener('click', this.fixIOS) }, 0) } }, handleBlur () { document.removeEventListener('selectionchange', this.handleSelectionChange) this.updateChatInputFocus(false) // 定时防止@列表/右键粘贴点击前消失 if (this.selectionAfterAt || this.isShowContextmenu) { setTimeout(() => { this.selectionAfterAt = false this.isShowContextmenu = false }, 200) } if (this.isIOS) { let scrollTop = document.body.scrollTop document.body.scrollTop = scrollTop this.$root.$el.removeEventListener('click', this.fixIOS) } mobileInputBlur() }, handleEsc () { this.selectionAfterAt = false }, /** * 监听光标位置 */ handleSelectionChange () { let el = this.$refs.chatInput if (!el) return let selectionStart = el.selectionStart let selectionEnd = this.$refs.chatInput.selectionEnd if (selectionStart !== selectionEnd) return let prevStr = this.getStrBeforeSelection() this.selectionAfterAt = /@/.test(prevStr) if (this.selectionAfterAt) { this.keyAfterAt = prevStr.slice(prevStr.lastIndexOf('@') + 1) let isNewAt = this.keyAfterAt.indexOf(this.lastKeyAfterAt) < 0 this.$store.commit('updateIsNewAt', { isNewAt: isNewAt, isNewAtFound: isNewAt ? false : this.group.isNewAtFound }) if (isNewAt) this.$store.commit('updateGroupSearchList', []) this.lastKeyAfterAt = this.keyAfterAt } }, // 监听右键 handleContextmenu (ev) { if (!this.copyText) return this.isShowContextmenu = !this.isShowContextmenu if (this.isShowContextmenu) { this.menuTop = ev.offsetY this.menuLeft = ev.offsetX > 100 ? ev.offsetX - 30 : ev.offsetX } }, // 监听粘贴 handlePaste () { this.isShowContextmenu = false this.inputMsg += this.copyText }, // 关闭emoji面板 closeEmojiList () { this.emojiShow = false }, fixIOS (event) { setTimeout(() => { if (this.$refs.chatInput === document.activeElement) { document.activeElement.blur() } }, 0) } } } // export const addPanelSessionMixin = { methods: { addPanelSession (serverId, sessionId) { // 先判断serverId有没有在sessionList let isInSession = this.sessionList.some(v => { return v.session_id == sessionId }) if (!isInSession) { // 没有就加入一个会话 api.user.getOtherInfo({ target_id: serverId }).then(({ data }) => { let userInfo = data.data let obj = { cover_photo: userInfo.cover_photo, is_group: '0', name: userInfo.nick_name, session_id: sessionId, unread: 0 } this.$store.commit('addSessionItem', obj) }) } } } } // 切换语言 export const changeLangMixin = { data () { return { curLang: getUserOpt('lang') || getLanguage() } }, methods: { changeLang () { let changeLang = this.curLang == 'en' ? 'zh' : 'en' this.$i18n.locale = changeLang this.curLang = changeLang // localStorage.setItem('lang', changeLang) setUserOpt('lang', changeLang) } } }