123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544 |
- <template>
- <view class="chat">
- <view class="chat-content" @touchstart="hideDrawer">
- <scroll-view id="chat-content-srcoll" scroll-y="true" :scroll-with-animation="scrollAnimation"
- :scroll-top="scrollTop" :scroll-into-view="scrollToView" @scrolltoupper="loadHistory"
- upper-threshold="50">
-
- <view class="chat-content-srcoll-loading" v-if="isHistoryLoading">
- <view class="spinner">
- <view class="rect1"></view>
- <view class="rect2"></view>
- <view class="rect3"></view>
- <view class="rect4"></view>
- <view class="rect5"></view>
- </view>
- </view>
-
- <view class="chat-content-srcoll-list">
- <view class="chat-content-srcoll-list-item" v-for="(item, index) in msgList" :key="index"
- :id="item.ID">
-
- <block>
-
- <view class="my-info" v-if="item.flow === 'out'">
-
- <view class="my-info-left">
-
- <view class="">
- <view class="my-username">
- <view class="time">{{ timeFliter(item.time) }}</view>
- <view class="time">{{ item.nick }}</view>
- </view>
- <view v-if="item.type === TIM.TYPES.MSG_TEXT" class="bubble">
- <rich-text :nodes="nodesFliter(item.payload.text)"></rich-text>
- </view>
- <view class="bubble" v-else-if="item.type === TIM.TYPES.MSG_IMAGE">
- <u-image :src="item.payload.imageInfoArray[0].imageUrl"
- :width="item.payload.imageInfoArray[0].width > 400 ? 400 : item.payload.imageInfoArray[0].width"
- :height="item.payload.imageInfoArray[0].height > 400 ? 400 : item.payload.imageInfoArray[0].height"
- border-radius="10"
- @click="previewImage(item.payload.imageInfoArray[0].imageUrl)"></u-image>
- </view>
- <view v-else-if="item.type === TIM.TYPES.MSG_CUSTOM" class="bubble">
- <view>
- {{ item.flow === 'out' ? '发起' : '接收' }}{{ JSON.parse(JSON.parse(item.payload.data).data).call_type == 1 ? '语音通话' : '视频通话' }}
- </view>
- </view>
- </view>
- </view>
-
- <view class="my-info-right">
- <u-avatar :src="item.avatar" size="80" mode="square" bg-color="#fff"></u-avatar>
- </view>
- </view>
-
- <view class="other-info" v-else>
-
- <view class="other-info-left">
- <u-avatar :src="item.avatar" size="80" mode="square" bg-color="#fff"></u-avatar>
- </view>
-
- <view class="other-info-right">
- <view class="username">
- <view class="name">{{ item.nick }}</view>
- <view class="time">{{ timeFliter(item.time) }}</view>
- </view>
-
- <view v-if="item.type === TIM.TYPES.MSG_TEXT" class="bubble">
- <rich-text :nodes="nodesFliter(item.payload.text)"></rich-text>
- </view>
- <view class="bubble" v-else-if="item.type === TIM.TYPES.MSG_IMAGE">
- <u-image :src="item.payload.imageInfoArray[0].imageUrl"
- :width="item.payload.imageInfoArray[0].width > 400 ? 400 : item.payload.imageInfoArray[0].width"
- :height="item.payload.imageInfoArray[0].height > 400 ? 400 : item.payload.imageInfoArray[0].height"
- border-radius="10"
- @click="previewImage(item.payload.imageInfoArray[0].imageUrl)"></u-image>
- </view>
- <view v-else-if="item.type === TIM.TYPES.MSG_CUSTOM" class="bubble">
- <view>
- {{ item.flow === 'out' ? '发起' : '接收' }}{{ JSON.parse(JSON.parse(item.payload.data).data).call_type == 1 ? '语音通话' : '视频通话' }}
- </view>
- </view>
- </view>
- </view>
- </block>
- </view>
- </view>
- </scroll-view>
- </view>
-
- <view class="input-box" :class="popupLayerClass" @touchmove.stop.prevent="discard">
- <view class="more" @tap="showMore">
- <view class="icon add"></view>
- </view>
- <view class="textbox">
- <view class="text-mode">
- <view class="box">
- <textarea auto-height="true" v-model="textMsg" @focus="textareaFocus" />
- </view>
- <view class="em" @tap="chooseEmoji">
- <view class="icon biaoqing"></view>
- </view>
- </view>
- </view>
- <view class="send" @tap="sendText">
- <view class="btn">发送</view>
- </view>
- </view>
-
- <view class="popup-layer" :class="popupLayerClass" @touchmove.stop.prevent="discard">
-
- <swiper class="emoji-swiper" :class="{ hidden: hideEmoji }" indicator-dots="true" duration="150">
- <swiper-item v-for="(page,pid) in emojiList" :key="pid">
- <view v-for="(em, eid) in page" :key="eid" @tap="addEmoji(em)">
- <image mode="widthFix" :src="'/static/img/emoji/'+ em.url"></image>
- </view>
- </swiper-item>
- </swiper>
-
- <view class="more-layer" :class="{ hidden: hideMore }">
- <view class="list">
- <view class="box" @tap="chooseImage">
- <view class="icon tupian2"></view>
- </view>
- <view class="box" @tap="camera">
- <view class="icon paizhao"></view>
- </view>
-
- </view>
- </view>
- </view>
-
-
- </view>
- </template>
- <script>
-
- import {
- mapState
- } from 'vuex';
- export default {
- components: {
-
- },
- data() {
- return {
-
- isHistoryLoading: false,
- scrollAnimation: false,
- scrollTop: 0,
- scrollToView: '',
-
- conversationActive: null,
- toUserId: '',
- toUserInfo: null,
- userInfo: null,
- msgList: [],
- nextReqMessageID: '',
- count: 15,
- isCompleted: '',
- TIM: null,
-
- popupLayerClass: '',
- isVoice: false,
- emojiList: this.$commen.emojiList,
- recording: false,
- textMsg: '',
-
- hideEmoji: true,
-
- hideMore: true
- }
- },
- onLoad(page) {
- if (page.title) {
- uni.setNavigationBarTitle({
- title: page.title
- })
- }
- this.conversationActive = this.$store.state.conversationActive;
- this.toUserId = this.$store.state.toUserId;
- this.TIM = this.$TIM
- this.getMsgList();
- },
- onShow() {
- this.scrollTop = 9999999;
- this.isHistoryLoading = false;
- this.readMessage();
-
-
-
- },
- computed: {
- ...mapState({
- currentMessageList: state => state.currentMessageList
- })
- },
- watch: {
- currentMessageList(newVal, oldVal) {
- this.msgList = newVal
- this.screenMsg(newVal, oldVal)
- }
- },
- onUnload() {
- this.readMessage();
- },
- methods: {
-
- readMessage() {
-
- console.log(this.conversationActive.conversationID)
- this.tim.setMessageRead({
- conversationID: this.conversationActive.conversationID
- }).then(function(imResponse) {
- console.log('全部已读')
-
- }).catch(function(imError) {
-
- console.warn('setMessageRead error:', imError);
- });
- },
-
- getMsgList() {
-
- let conversationID = this.conversationActive.conversationID
- this.tim.getMessageList({
- conversationID: conversationID,
- count: this.count
- }).then((res) => {
- console.log(res.data)
- this.$store.commit('pushCurrentMessageList', res.data.messageList)
- this.nextReqMessageID = res.data.nextReqMessageID
- this.isCompleted = res.data.isCompleted
- this.scrollToView = res.data.messageList[res.data.messageList.length - 1]?.ID
- }).catch(err => {
- console.log(err)
-
-
-
- })
-
- this.$nextTick(function() {
-
- this.scrollTop = 9999;
- this.$nextTick(function() {
- this.scrollAnimation = true;
- });
- });
- },
-
- screenMsg(newVal, oldVal) {
- if (newVal[0] && oldVal[0]) {
- if (newVal[0].ID != oldVal[0].ID && newVal.length >= this.count) {
- let _index = newVal.length - oldVal.length - 1
- this.$nextTick(() => {
- this.scrollToView = newVal[_index].ID
- });
-
- } else {
-
- this.$nextTick(() => {
- this.scrollToView = newVal[newVal.length - 1].ID
- });
- }
- } else {
-
- this.$nextTick(() => {
- this.scrollToView = newVal[newVal.length - 1].ID;
- this.scrollTop = 9999999;
- });
- }
- },
-
- timeFliter(timer) {
- let timeData = new Date(timer * 1000)
- let str = this.$format.dateTimeFliter(timeData)
- return str
- },
-
- nodesFliter(str) {
- let nodeStr = '<div style="align-items: center;word-wrap:break-word;">' + str + '</div>'
- return nodeStr
- },
-
- hideDrawer() {
- this.popupLayerClass = '';
- setTimeout(() => {
- this.hideMore = true;
- this.hideEmoji = true;
- }, 150);
- },
-
- chooseEmoji() {
- this.hideMore = true;
- if (this.hideEmoji) {
- this.hideEmoji = false;
- this.openDrawer();
- } else {
- this.hideDrawer();
- }
- },
-
- loadHistory(e) {
- this.isHistoryLoading = true;
-
- let conversationID = this.conversationActive.conversationID
- this.tim.getMessageList({
- conversationID: conversationID,
- nextReqMessageID: this.nextReqMessageID,
- count: this.count
- }).then((res) => {
- this.$store.commit('unshiftCurrentMessageList', res.data.messageList)
- this.nextReqMessageID = res.data.nextReqMessageID
- this.isCompleted = res.data.isCompleted
- this.isHistoryLoading = false;
- });
- },
-
- textareaFocus() {
- if (this.popupLayerClass == 'showLayer' && this.hideMore == false) {
- this.hideDrawer();
- }
- },
-
- sendText() {
- this.hideDrawer();
- if (!this.textMsg) {
- return;
- }
- let content = this.replaceEmoji(this.textMsg);
- let msg = {
- text: content
- }
- this.sendMsg(msg, 'text');
- this.textMsg = '';
- },
-
- sendMsg(content, type) {
- let message;
- if (type === 'text') {
- message = this.tim.createTextMessage({
- to: this.toUserId,
- conversationType: 'C2C',
- payload: {
- text: content.text
- }
- });
- } else if (type === 'img') {
- message = this.tim.createImageMessage({
- to: this.toUserId,
- conversationType: 'C2C',
- payload: {
- file: content
- }
- })
- }
- this.$store.commit('pushCurrentMessageList', message)
- this.tim.sendMessage(message).then(res => {
- this.$nextTick(() => {
-
- this.scrollToView = res.data.message.ID
- });
- })
- },
-
- replaceEmoji(str) {
- let replacedStr = str.replace(/\[([^(\]|\[)]*)\]/g, (item, index) => {
- for (let i = 0; i < this.emojiList.length; i++) {
- let row = this.emojiList[i];
- for (let j = 0; j < row.length; j++) {
- let EM = row[j];
- if (EM.alt == item) {
-
-
- let onlinePath = 'http://veterhchat.hw.hongweisoft.com/static/img/emoji/'
- let imgstr = '<img src="' + onlinePath + EM.url + '">';
- return imgstr;
- }
- }
- }
- });
- return replacedStr;
- },
-
- showMore() {
- this.hideEmoji = true;
- if (this.hideMore) {
- this.hideMore = false;
- this.openDrawer();
- } else {
- this.hideDrawer();
- }
- },
- discard() {
- return;
- },
-
- openDrawer() {
- this.popupLayerClass = 'showLayer';
- },
-
- hideDrawer() {
- this.popupLayerClass = '';
- setTimeout(() => {
- this.hideMore = true;
- this.hideEmoji = true;
- }, 150);
- },
-
- addEmoji(em) {
- this.textMsg += em.alt;
- },
-
- chooseImage() {
- this.getImage('album');
- },
-
- camera() {
- this.getImage('camera');
- },
-
- call(type) {
- this.trtcCalling.call({
- userID: this.toUserId,
- type: type,
- timeout: 300
- }).then((res) => {
- console.log('成功:', res)
- this.$refs.trtcCalling.openDialog()
- }).catch(err => {
- console.log('失败', err)
- uni.showToast({
- title: '调用通话失败',
- icon: 'none'
- })
- })
- },
-
- getImage(type) {
- this.hideDrawer();
- uni.chooseImage({
- sourceType: [type],
- sizeType: ['original', 'compressed'],
- success: (res) => {
- this.sendMsg(res.tempFiles[0], 'img')
- },
- fail: (err) => {
- uni.showToast({
- icon: 'none',
- title: '图片上传失败!'
- })
- }
- });
- },
-
- previewImage(img) {
- uni.previewImage({
- urls: [img]
- });
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- @font-face {
- font-family: "iconfont";
-
- src: url('//at.alicdn.com/t/font_2965205_e6crsnlz8jf.woff2?t=1637829206479') format('woff2'),
- url('//at.alicdn.com/t/font_2965205_e6crsnlz8jf.woff?t=1637829206479') format('woff'),
- url('//at.alicdn.com/t/font_2965205_e6crsnlz8jf.ttf?t=1637829206479') format('truetype');
- }
- .iconfont {
- font-family: "iconfont" !important;
- font-size: 16px;
- font-style: normal;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- }
- .icon-yuyin:before {
- content: "\e6e1";
- }
- .icon-shipin:before {
- content: "\e64f";
- }
- @import './chat.scss';
- </style>
|