123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- <template>
- <div class="c-view">
- <div class="box">
- <div class="box-hd">
- <div class="title-wrap">
- {{isPrivate ? group.privateName : group.groupName}}
- <i class="el-icon-more" v-if="!isPrivate" @click="groupSet = !groupSet"></i>
- </div>
- </div>
- <chat-pin v-bind="pinMsg" @pinMsgClose="pinMsgClose" @scrollToView="scrollToView"></chat-pin>
- <div class="box-bd" :style="{height:scrollHeight - (pinMsg.visible ? 30 : 0) + 'px'} ">
- <div ref="scrollWrap" class="bar" @scroll="handleScroll">
- <div ref="msgWrap" class="scroll-wrapper">
- <div 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, key) in group.chatList"
- :key="key"
- :isPrivate ="isPrivate"
- :msgItem="item"
- v-bind="item"
- @quoteMsg="quoteMsg"
- @deleteMsg="deleteMsg"
- >
- </msg-item>
- </div>
- </div>
- </div>
- <at-me v-if="!isPrivate" :atList="atList" @scrollToMsg="scrollToMsg"></at-me>
- <div class="msg-unread"
- @click="doSetRead"
- v-if="group.unreadNums > 0 && enableScroll">
- <em><i class="el-icon-d-arrow-right"></i>{{group.unreadNums}}条未读消息</em>
- </div>
- </div>
- <input-area ref="inputArea" @toBottom="resizeToBottom"></input-area>
- </div>
- <chat-set
- v-if="group.members && !isPrivate"
- :class="{'move-left': groupSet}">
- </chat-set>
- </div>
- </template>
- <script>
- import Vue from 'vue'
- import msgItem from '@/components/msgItem'
- import chatPin from '@/components/chatPin'
- import atMe from '@/components/chatAt/atme'
- import { mapActions, mapState, mapMutations } from 'vuex'
- import chatSet from '@/components/chatSet'
- import inputArea from './inputArea'
- import { getResizeHeight, scrollMsgIntoView } from '@/util/util.js'
- import { Button } from 'element-ui'
- Vue.component(Button.name, Button)
- export default {
- name: 'chatRoom',
- components: {
- msgItem,
- inputArea,
- chatSet,
- chatPin,
- atMe
- },
- props: {
- sessionId: [String, Number]
- },
- watch: {
- sessionId (val) {
- // 切换房间
- this.groupSet = false
- this.lockMore = false
- this.lockEnd = false
- this.enableScroll = false
- this.initRoom()
- },
- unreadNums (val, newval) {
- if (val > 0 && this.isBottom) {
- this.resizeToBottom()
- }
- }
- },
- data () {
- return {
- groupSet: false,
- lockMore: false,
- lockEnd: false,
- enableScroll: false, // 记录滚动条是否激活的状态
- isBottom: true,
- scrollHeight: 100, // 滚动条高度
- isScrollToView: false
- }
- },
- computed: {
- ...mapState([
- 'group',
- 'userId',
- 'userInfo'
- ]),
- ...mapState({
- pinMsg: state => state.group.pinMsg,
- pinList: state => state.group.pinList,
- atList: state => state.group.atList
- }),
- isPrivate () {
- return /-/g.test(this.sessionId)
- }
- },
- mounted () {
- this.scrollHeight = getResizeHeight()
- window.onresize = () => {
- this.scrollHeight = getResizeHeight()
- }
- this.initRoom()
- document.addEventListener('contextmenu', e => e.preventDefault())
- },
- methods: {
- ...mapMutations([
- 'initGroup',
- 'resetUnreadNums',
- 'addChatItem',
- 'deleteChatItem',
- 'initState',
- 'clearAtList'
- ]),
- ...mapActions([
- 'getGroupInfo',
- 'getNewMsg',
- 'getHistoryMsg',
- 'doSendMsg',
- 'getPrivateNewMsg',
- 'getPrivateHistoryMsg',
- 'doSendPrivateMsg'
- ]),
- initRoom () {
- this.initState(this.userInfo)
- if (this.isPrivate) {
- this.initPersonChat()
- } else {
- this.initGroupChat()
- }
- },
- /**
- * @des 私聊初始化处理
- */
- async initPersonChat () {
- await this.getPrivateNewMsg()
- this.$nextTick(this.resizeToBottom)
- },
- /**
- * @des 聊天群初始化处理
- */
- async initGroupChat () {
- this.initGroup({
- userId: this.userId,
- groupId: this.sessionId,
- useCache: false
- })
- await this.getGroupInfo()
- await this.getNewMsg()
- this.$nextTick(this.resizeToBottom)
- },
- /**
- * @des 滚动事件监听
- */
- initScrollEvent () {
- },
- /**
- * @des 聊天窗体滚动事件处理集
- */
- async handleScroll (e) {
- // 防止切换房间时触发滚动处理
- if (!this.group.chatList.length) {
- return
- }
- // 防止滚动到置顶消息触发滚动
- if (this.isScrollToView) {
- return
- }
- // 激活滚动条
- this.enableScroll = true
- let totalHeight = this.$refs.msgWrap.offsetHeight
- let scrollTop = e.target.scrollTop
- // 差不多滚动到顶部
- if (scrollTop === 0 && !this.lockMore) {
- if (this.group.endHash !== null) {
- this.lockMore = true
- let res
- if (this.isPrivate) {
- res = await this.getPrivateHistoryMsg()
- } else {
- res = await this.getHistoryMsg()
- }
- if (res === 'end') {
- this.lockEnd = true
- } else {
- let scrollBottom = totalHeight - scrollTop
- this.$nextTick(() => {
- e.target.scrollTop = this.$refs.msgWrap.offsetHeight - scrollBottom
- setTimeout(() => {
- this.lockMore = false
- }, 800)
- })
- }
- }
- }
- // 滚动到底部清空未读消息状态
- if (scrollTop + e.target.offsetHeight > totalHeight) {
- this.isBottom = true
- if (this.group.unreadNums) {
- this.resetUnreadNums()
- }
- } else {
- this.isBottom = false
- }
- },
- /**
- * @des 聊天窗体滚动到底部
- */
- resizeToBottom () {
- this.$refs.scrollWrap.scrollTop = this.$refs.msgWrap.offsetHeight
- this.resetUnreadNums()
- this.isBottom = true
- },
- /**
- * @des 点击,查看未读消息
- * 直接滚动到聊天列表底部
- */
- doSetRead () {
- this.resizeToBottom()
- },
- /**
- * @des 引用某条消息
- */
- quoteMsg (msg) {
- this.$refs.inputArea.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.clearAtList()
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- @import './chatRoom.scss';
- </style>
|