123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884 |
- <template>
- <div class="mini-wrap">
- <div class="mini-body" :class="{'moblie-wrap': isMobile}" v-show="showChat">
- <div class="box">
- <div class="box-hd">
- <div class="btn-menu" @click.stop="showMenuExtra = !showMenuExtra"></div>
- <div class="btn-close" @click="handleToggleChat(false)"></div>
- <div class="box-title">{{group.groupName}}</div>
- <div class="user-tips">
- <em>{{group.userCounts}}</em>
- </div>
- <ul class="menu-extra" v-show="showMenuExtra">
- <div class="info clearfix" v-if="account">
- <span class="avatar avatar-bg">{{account.name.slice(0,2).toUpperCase()}}</span>
- <span class="account-info">
- <em>{{account.name}}</em>
- <i class="login-out" href="javascript:void(0);" @click="handleLogout">注销</i>
- </span>
- </div>
- <li v-if="userId"><a :href="`/#/user/${userId}`" target="_blank">聊天账号设置<i class="icon-arrow"></i></a></li>
- <li v-if="group.groupId"><a :href="`/#/group/${group.groupId}`" target="_blank">在网页版打开聊天<i class="icon-arrow"></i></a></li>
- <li><a href="https://www.mee.chat/" target="_blank">Powered by MeeChat</a></li>
- </ul>
- </div>
- <chat-pin v-bind="pinMsg" @pinMsgClose="pinMsgClose" @scrollToView="scrollToView"></chat-pin>
- <div class="box-bd" ref="msgBox">
- <div ref="scrollWrap"
- @scroll.prevent="handleScroll"
- class="scroller"
- >
- <div ref="msgWrap" class="msg-wrap">
- <div class="msg-top-more" v-if="lockEnd">
- <em>没有更多了</em>
- </div>
- <div class="msg-top-load" v-if="lockMore && !lockEnd">
- <i class="msg-loading-icon"></i>
- </div>
- <template v-if="group.chatList.length">
- <msg-item v-for="(item ,key) in group.pinList"
- :key="'pin' + key"
- v-bind="item"
- @quoteMsg="quoteMsg"
- @deleteMsg="deleteMsg"
- >
- </msg-item>
- </template>
- <msg-item v-for="item in group.chatList"
- :key="item.hash"
- v-bind="item"
- :msgItem="item"
- @quoteMsg="quoteMsg"
- @deleteMsg="deleteMsg"
- ></msg-item>
- </div>
- </div>
- <at-me :atList="atList" class="mini" @scrollToMsg="scrollToMsg"></at-me>
- <div class="msg-unread"
- @click="doSetRead"
- v-if="unreadNums > 0 && enableScroll && !isBottom">
- <em><i class="el-icon-d-arrow-right"></i>{{unreadNums}}条未读消息</em>
- </div>
- </div>
- <div class="box-ft">
- <chat-at
- ref="chatAt"
- v-if="atShow"
- @atperson="atPerson"
- :curInd="atInd"
- :filterList="filterMembers">
- </chat-at>
- <div class="input-ctrl" v-if="showLoginBtn">
- <span v-if="showLoginBtn === 'loading'">登录中...</span>
- <span v-else class="enable" @click="handleLogin">登录</span>
- </div>
- <div class="input-con" v-else>
- <div class="more-icon" @click.stop="handleMoreClick"></div>
- <form class="input-wrap" @submit="handleSend">
- <textarea
- @keydown.up.prevent="handleUp"
- @keydown.down.prevent="handleDown"
- @keydown.left="handleLeft"
- @keydown.right="handleRight"
- @keydown.delete="handleDel"
- @keydown.esc="handleEsc"
- cols="1"
- ref="chatInput"
- rows="1"
- @keydown.enter="handleKeyDown"
- placeholder="Write a message"
- v-model="inputMsg"
- @focus="handleFocus"
- @blur="handleBlur"
- :style="{height:inputHeight}"
- />
- </form>
- <div class="emoji-icon" @click.stop="handleEmojiClick"></div>
- <div class="btn-send" @click="handleSend">发送</div>
- </div>
- <div class="tool-wrap" @click.stop v-show="toolShow">
- <div class="tool-item">
- <div class="icon-box" @click="$packetSend">
- <i class="packet-icon"></i>
- </div>
- <span class="type">红包</span>
- </div>
- <div class="tool-item">
- <div class="icon-box">
- <i class="picture-icon"></i>
- <input type="file" ref="inputFile1" name="res" accept="image/*" @change="handleFile">
- </div>
- <span class="type">图片</span>
- </div>
- <div class="tool-item">
- <div class="icon-box">
- <i class="audio-icon"></i>
- <input type="file" ref="inputFile2" name="res" accept="audio/*" @change="handleFile">
- </div>
- <span class="type">音频</span>
- </div>
- <div class="tool-item">
- <div class="icon-box">
- <i class="video-icon"></i>
- <input type="file" ref="inputFile3" name="res" accept="video/*" @change="handleFile">
- </div>
- <span class="type">视频</span>
- </div>
- </div>
- <div class="emoji-wrap" v-if="showEmoji">
- <emoji-list @addEmoji="addEmoji"></emoji-list>
- </div>
- </div>
- </div>
- </div>
- <div @click="handleToggleChat(true)" class="mini-control" v-show="!showChat">
- <i class="at-tip" v-show="atList.length">@</i>
- <ul v-if="unreadCounts > 0">
- <li class="msg-tips">
- <em>+{{unreadCounts}}</em>
- </li>
- <li class="user-tips">
- <em>{{group.userCounts}}</em>
- </li>
- </ul>
- <div class="meechat-icon" v-else>
- <i class="user-tips">
- <em>{{group.userCounts}}</em>
- </i>
- </div>
- </div>
- </div>
- </template>
- <script>
- import msgItem from '@/components/msgItem'
- import emojiList from '@/components/emoji'
- import chatAt from '@/components/chatAt'
- import atMe from '@/components/chatAt/atme'
- import chatPin from '@/components/chatPin'
- import { mapActions, mapState, mapMutations } from 'vuex'
- import { getMiniWsUrl } from '@/util/contract.js'
- import { isMobile, scrollMsgIntoView } from '@/util/util.js'
- import WsManager from '@/util/wsManager.js'
- import PostMessager from '@/util/postMessager.js'
- import ScatterJS from 'scatter-js/dist/scatter.esm'
- import { Message } from 'element-ui'
- import ImageMin from '@/util/imageMin.js'
- import { chatAtMixin, chatInputMixin } from '@/mixins'
- export default {
- name: 'chatMini',
- mixins: [chatAtMixin, chatInputMixin],
- components: {
- msgItem,
- emojiList,
- chatAt,
- chatPin,
- atMe
- },
- props: {
- width: {
- type: Number,
- default: 274
- },
- height: {
- type: Number,
- default: 390
- },
- show: {
- type: Boolean,
- default: false
- },
- groupId: [Number, String]
- },
- computed: {
- ...mapState([
- 'account',
- 'group',
- 'userId',
- 'userInfo'
- ]),
- ...mapState({
- chatInputFocus: state => state.group.chatInputFocus,
- blockList: state => state.group.blockList,
- pinMsg: state => state.group.pinMsg,
- pinList: state => state.group.pinList,
- atList: state => state.group.atList,
- unreadNums: state => state.group.unreadNums
- })
- },
- data () {
- return {
- isMobile: isMobile(),
- showChat: !!this.show, // 显示聊天窗
- showEmoji: false, // 显示表情选择框
- showMenuExtra: false, // 显示左上角菜单
- showLoginBtn: true, // 显示登录按钮
- lockMore: false,
- isScrollToView: false,
- lockEnd: false,
- loading: false,
- unreadCounts: 0, // 未读消息数
- inputMsg: '', // 用户输入的内容
- atInd: 0, // @人索引
- inputHeight: 18,
- enableScroll: false, // 记录滚动条是否激活的状态
- isBottom: true,
- toolShow: false
- }
- },
- watch: {
- inputMsg (val, newval) {
- let ele = this.$refs.chatInput
- this.inputHeight = 'auto'
- this.$nextTick(() => {
- this.inputHeight = Math.max(18, Math.min(ele.scrollHeight, 75)) + 'px'
- })
- },
- unreadNums (val, newval) {
- if (val > 0 && this.isBottom) {
- setTimeout(this.resizeToBottom.bind(this), 150)
- }
- },
- chatInputFocus (val, newval) {
- if (this.showLoginBtn) return
- let ele = this.$refs.chatInput
- if (val) {
- if (document.activeElement !== ele) {
- this.placeEnd(ele)
- ele.focus()
- }
- } else {
- if (document.activeElement === ele) {
- ele.blur()
- }
- }
- }
- },
- async mounted () {
- // 初始化postMessage消息管理器
- let callback = (event) => {
- if (event.action === 'meechat:setShow') {
- this.handleToggleChat(event.show)
- } else if (event.action === 'meechat:logout') {
- this.handleLogout2()
- }
- }
- this.postMessager = new PostMessager('*', { callback })
- window.postMessager = this.postMessager
- // 设置groupId
- this.initGroup({
- userId: this.userId,
- groupId: this.groupId,
- useCache: false
- })
- // 检查登录态
- let userId = localStorage.getItem('user_id')
- let token = localStorage.getItem('token')
- let account = localStorage.getItem('account')
- if (userId && token && account) {
- this.setUserId(userId)
- this.setToken(token)
- this.setAccount(JSON.parse(account))
- this.showLoginBtn = false
- await this.getUserInfo()
- }
- this.$nextTick(this.initChat)
- this.$nextTick(this.initSocket)
- document.addEventListener('contextmenu', e => e.preventDefault())
- document.addEventListener('paste', this.initPaste)
- document.addEventListener('drop', this.initDrop)
- document.addEventListener('dragover', this.initDragOver)
- document.body.addEventListener('click', () => {
- this.showEmoji = false
- this.showMenuExtra = false
- this.toolShow = false
- })
- },
- beforeDestroy () {
- document.removeEventListener('paste', this.initPaste)
- document.removeEventListener('drop', this.initDrop)
- document.removeEventListener('dragover', this.initDragOver)
- },
- methods: {
- ...mapMutations([
- 'initGroup',
- 'setUserId',
- 'setToken',
- 'addChatItem',
- 'deleteChatItem',
- 'updateChatInputFocus',
- 'updateGroupBlockList',
- 'updateMembers',
- 'updateGroupPinMsg',
- 'repealChatItem',
- 'removeAtListLast',
- 'clearAtList',
- 'initState',
- 'addPacketItem',
- 'addPacketTip',
- 'addUnreadNums',
- 'resetUnreadNums'
- ]),
- ...mapActions([
- 'getUserInfo',
- 'setScatter',
- 'setAccount',
- 'doGameLogin',
- 'doScatterLogin',
- 'doScatterLogout',
- 'getGroupInfo',
- 'getNewMsg',
- 'getHistoryMsg',
- 'doSendMsg',
- 'doSendFile',
- 'doContractLogin'
- ]),
- handleMoreClick () {
- this.showEmoji = false
- this.toolShow = !this.toolShow
- },
- handleEmojiClick () {
- this.toolShow = false
- this.showEmoji = !this.showEmoji
- },
- // 连接socket
- initSocket () {
- if (!window.WebSocket) {
- console.log('Error: WebSocket is not supported .')
- return
- }
- let host = getMiniWsUrl() + `?group_id=${this.groupId}`
- if (this.socket) {
- this.socket.destroy()
- this.socket = null
- }
- this.socket = new WsManager(host, {
- autoConnect: true, // 自动连接
- reconnection: true, // 断开自动重连
- reconnectionDelay: 2000 // 重连间隔时间,单位秒
- })
- this.socket.on('open', res => {})
- this.socket.on('message', (data) => {
- data = JSON.parse(data)
- if (data.channel.match('chat:group')) {
- if (data.data.type === 'msg' && data.data.from != this.userId) {
- this.getNewMsg({ newMsg: true })
- // 未读消息数+1
- if (!this.showChat) {
- if (this.unreadCounts === 0) {
- this.postResize(130, 50)
- }
- this.unreadCounts++
- } else {
- this.addUnreadNums()
- }
- }
- if (data.data.type === 'repeal') {
- this.repealChatItem(data.data)
- }
- if (data.data.type === 'block') {
- this.updateGroupBlockList({
- type: 'add',
- id: data.data.to
- })
- }
- if (data.data.type === 'unblock') {
- this.updateGroupBlockList({
- type: 'delete',
- id: data.data.to
- })
- }
- if (data.data.type === 'join') {
- this.updateMembers(data.data.user_info)
- }
- if (data.data.type === 'pin_msg') {
- this.updateGroupPinMsg(data.data.pinMsg)
- }
- if (data.data.type === 'unpin_msg') {
- this.updateGroupPinMsg(null)
- }
- if (data.data.type === 'new_redpack') {
- this.addPacketItem(data.data)
- if (data.data.from == this.userId) {
- this.$nextTick(this.resizeToBottom)
- }
- }
- if (data.data.type === 'grab_redpack') {
- if (data.data.from == this.userId || data.data.to == this.userId) {
- this.addPacketTip(data.data)
- }
- }
- }
- })
- },
- /**
- * 聊天群初始化处理
- * 先后调用 group/info, group/msg
- */
- async initChat () {
- this.handleToggleChat(this.show)
- await this.getGroupInfo()
- await this.getNewMsg()
- if (this.show) {
- this.$nextTick(this.resizeToBottom)
- }
- },
- async handleLogout () {
- this.doScatterLogout()
- this.showLoginBtn = true
- if (self !== top) {
- localStorage.removeItem('account')
- this.postMessager.send({
- action: 'meechat:logout'
- })
- }
- // 注销后,刷新页面
- location.replace(location.href.replace('show=false', 'show=true'))
- },
- async handleLogout2 () {
- this.doScatterLogout()
- this.showLoginBtn = true
- },
- /**
- * 登录处理
- */
- async handleLogin () {
- // 设置登录按钮状态
- this.showLoginBtn = 'loading'
- if (self !== top) {
- this.handleParentLogin()
- } else {
- // 连接scatter
- this.scatterConnect()
- }
- },
- scatterConnect () {
- ScatterJS.scatter.connect('MEE_CHAT').then(async connected => {
- if (connected) {
- try {
- // 设置scatter
- this.setScatter(ScatterJS.scatter)
- // 清空全局scatter引用
- window.ScatterJS = null
- // 调起scatter授权登录
- await this.doScatterLogin()
- localStorage.setItem('account', JSON.stringify(this.account))
- // 合约登录
- await this.doContractLogin()
- this.showLoginBtn = false
- this.initGroup({
- userId: this.userId,
- groupId: this.groupId,
- useCache: false
- })
- await this.getUserInfo()
- } catch (ex) {
- this.showLoginBtn = true
- }
- }
- })
- },
- /**
- * @des 调用父级页面getIdentity
- */
- async getParentIdentity () {
- if (self !== top) {
- try {
- let response = await this.postMessager.send({ action: 'meechat:getIdentity' })
- let account = response.accounts.find(x => x.blockchain === 'eos')
- localStorage.setItem('account', JSON.stringify(account))
- this.setAccount(account)
- } catch (error) {
- this.showLoginBtn = true
- }
- }
- },
- /**
- * @des 调用父级页面登录
- */
- async handleParentLogin () {
- try {
- // scatter登录
- await this.getParentIdentity()
- if (!this.account) return
- // 合约登录
- await this.doContractLogin()
- location.replace(location.href.replace('show=false', 'show=true'))
- } catch (msg) {
- if (msg.type) {
- // scatter报错的情况
- } else {
- let json = JSON.parse(msg)
- let details = json.error.details
- Message({
- message: details[0].message,
- type: 'error'
- })
- }
- this.showLoginBtn = true
- }
- },
- /**
- * 聊天窗体滚动到底部
- */
- resizeToBottom () {
- this.$refs.scrollWrap.scrollTop = this.$refs.msgWrap.offsetHeight
- this.resetUnreadNums()
- this.isBottom = true
- },
- /**
- * @des 点击,查看未读消息
- * 直接滚动到聊天列表底部
- */
- doSetRead () {
- this.resizeToBottom()
- },
- /**
- * 添加表情
- */
- addEmoji (value) {
- this.inputMsg += value
- },
- /**
- * @des 聊天窗体滚动事件处理集
- */
- handleScroll (e) {
- this.enableScroll = true
- e.target.focus()
- // 防止切换房间时触发滚动处理
- if (!this.group.chatList.length) {
- return
- }
- // 防止滚动到置顶消息触发滚动
- if (this.isScrollToView) {
- return
- }
- let msgWrap = this.$refs.msgWrap
- let totalHeight = msgWrap.offsetHeight
- let scrollTop = e.target.scrollTop
- if (scrollTop === 0 && !this.lockMore) {
- if (this.group.endHash !== null) {
- this.lockMore = true
- this.getHistoryMsg().then((res) => {
- if (res === 'end') {
- this.lockEnd = true
- } else {
- let scrollBottom = totalHeight - scrollTop
- this.$nextTick(() => {
- e.target.scrollTop = msgWrap.offsetHeight - scrollBottom
- this.ps && this.ps.update()
- setTimeout(() => {
- this.lockMore = false
- }, 800)
- })
- }
- })
- }
- }
- // 滚动到底部清空未读消息状态
- if (scrollTop + e.target.offsetHeight > totalHeight) {
- this.isBottom = true
- if (this.unreadNums) {
- this.resetUnreadNums()
- }
- } else {
- this.isBottom = false
- }
- // let wheelUp = e.deltaY < 0
- // let wheelDown = e.deltaY > 0
- // let scrollDist = e.target.scrollHeight - e.target.clientHeight
- // console.log(e, wheelDown, scrollDist)
- // if ((scrollTop <= 0) && wheelUp) {
- // e.preventDefault()
- // return false
- // }
- // if ((scrollTop >= scrollDist) && wheelDown) {
- // e.preventDefault()
- // return false
- // }
- },
- /**
- * @des 处理消息发送
- */
- async handleSend (e) {
- // 判断是否被禁言
- if (this.blockList.some(id => id == this.userId)) {
- Message({
- message: '您已被禁言',
- type: 'error'
- })
- return
- }
- let text = this.inputMsg.trim()
- if (text.length === 0) {
- Message({
- message: '聊天内容不能为空',
- type: 'warning'
- })
- return
- }
- let opt = {
- type: 0,
- msg: text
- }
- // 清空输入框
- this.inputMsg = ''
- // 用户不是第一次发言
- if (this.group.members[this.userId]) {
- let createTime = Date.now()
- this.addChatItem({
- from: this.userId,
- content: text,
- hash: `${createTime}`,
- timestamp: createTime,
- createTime,
- msg_type: '0',
- loading: true
- })
- opt.createTime = createTime
- this.doSendMsg(opt)
- } else {
- // 发言后,才滚动底部
- await this.doSendMsg(opt)
- }
- // 滚到底部
- this.$nextTick(function () {
- this.resizeToBottom()
- })
- e.preventDefault()
- return false
- },
- placeEnd (el) {
- var range = document.createRange()
- range.selectNodeContents(el)
- range.collapse(false)
- var sel = window.getSelection()
- sel.removeAllRanges()
- sel.addRange(range)
- },
- initDrop (e) {
- e.preventDefault()
- let files = Array.from(e.dataTransfer.files)
- files.forEach(file => this.handleFile(file))
- },
- initDragOver (e) {
- e.preventDefault()
- },
- initPaste (event) {
- var items = (event.clipboardData || window.clipboardData).items
- if (items && items.length) {
- Array.from(items).forEach(item => {
- let file = item.getAsFile()
- if (file) {
- this.handleFile(file)
- }
- })
- }
- },
- /**
- * 文件预处理
- * @return {Object} data 预处理文件信息
- * @param {Number} data.type
- * @param {File} data.res
- */
- async preHandleFile (file) {
- let type = file.type
- let size = file.size
- if (type.match('video')) {
- return size > 3 * 1024 * 1024 ? Promise.reject(new Error(file)) : Promise.resolve({
- type: 2,
- res: file
- })
- } else if (type.match('audio')) {
- return size > 2 * 1024 * 1024 ? Promise.reject(new Error(file)) : Promise.resolve({
- type: 3,
- res: file
- })
- } else if (type.match('image')) {
- let image = await new ImageMin({
- file: file,
- maxSize: 1024 * 1024
- })
- return {
- type: 1,
- preview: image.base64,
- res: image.res
- }
- }
- },
- /**
- * @des 处理文件发送
- */
- async handleFile (e) {
- let inputfile
- if (e.constructor === File) {
- inputfile = e
- } else {
- inputfile = e.target.files[0]
- }
- try {
- let fileInfo = await this.preHandleFile(inputfile)
- let opt = { res: fileInfo.res }
- if (this.group.members[this.userId]) {
- let createTime = Date.now()
- this.addChatItem({
- content: fileInfo.preview || '',
- from: this.userId,
- hash: `${createTime}`,
- msg_type: fileInfo.type,
- timestamp: createTime,
- res: fileInfo.res,
- loading: true,
- createTime
- })
- opt.createTime = createTime
- }
- this.doSendFile(opt)
- this.toolShow = false
- this.toolShow = false
- setTimeout(() => {
- this.$refs.inputFile1.value = null
- this.$refs.inputFile2.value = null
- this.$refs.inputFile3.value = null
- this.resizeToBottom()
- }, 100)
- } catch (error) {
- Message({
- message: '上传文件大小限制:音频2M以内,视频3M以内',
- type: 'warning'
- })
- }
- },
- /**
- * @des 控制聊天窗口开关
- */
- handleToggleChat (flag) {
- if (flag) {
- this.showChat = true
- this.unreadCounts = 0
- this.$nextTick(() => {
- this.postResize(this.width, this.height + 16)
- this.resizeToBottom()
- })
- } else {
- this.showChat = false
- this.$nextTick(() => {
- this.postResize(56, 50)
- })
- }
- },
- postResize (width, height) {
- let request = {
- action: 'meechat:resize',
- data: {
- ch: height,
- cw: width
- }
- }
- return window.parent.postMessage(request, '*')
- },
- /**
- * @des 引用某条消息
- */
- quoteMsg (msg) {
- this.inputMsg = msg
- },
- /**
- * @des 某条消息被删除
- */
- deleteMsg (hash) {
- this.deleteChatItem(hash)
- },
- pinMsgClose () {
- this.pinMsg.visible = false
- },
- scrollToView () {
- if (this.pinList.length) {
- let node = this.$refs.msgWrap.querySelector('.msg-item')
- scrollMsgIntoView(this.$refs.scrollWrap, node.offsetTop - (this.pinMsg ? 40 : 10), node)
- } else {
- let hash = this.pinMsg.hash
- let index = this.group.chatList.findIndex(item => item.hash === hash)
- if (index >= 0) {
- let node = this.$refs.msgWrap.querySelectorAll('.msg-item').item(index)
- scrollMsgIntoView(this.$refs.scrollWrap, node.offsetTop - (this.pinMsg ? 40 : 10), node)
- }
- }
- // 防止加载更多
- this.isScrollToView = true
- setTimeout(() => {
- this.isScrollToView = false
- }, 2000)
- },
- scrollToMsg (index) {
- let hash = this.atList[index].hash
- let eleIndex = this.group.chatList.findIndex(item => item.hash === hash)
- if (eleIndex >= 0) {
- let pinLen = this.group.pinList.length
- let node = this.$refs.msgWrap.querySelectorAll('.msg-item').item(eleIndex + pinLen)
- scrollMsgIntoView(this.$refs.scrollWrap, node.offsetTop - (this.pinMsg ? 40 : 10), node)
- }
- this.removeAtListLast()
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- @import "./chatMini.scss";
- </style>
|