123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600 |
- <!-- 聊天消息中心列表页面 -->
- <template>
- <view class="message_center">
- <!-- 消息类型 start -->
- <view class="message_type">
- <view class="message_type_con">
- <view class="message_type_pre" v-for="(item,index) in noticeList" :key="index"
- @click="linkTo(item.tplTypeCode,item.msgNum)">
- <image :src="system_news" mode="" v-if="item.tplTypeCode == 'system_news'"></image>
- <image :src="order_news" mode="" v-if="item.tplTypeCode == 'order_news'"></image>
- <image :src="assets_news" mode="" v-if="item.tplTypeCode == 'assets_news'"></image>
- <image :src="appointment_news" mode="" v-if="item.tplTypeCode == 'appointment_news'"></image>
- <image :src="after_sale_news" mode="" v-if="item.tplTypeCode == 'after_sale_news'"></image>
- <text>{{item.msgName}}</text>
- <text class="message_type_nums message_type_nums_9"
- v-if="item.msgNum>0">{{item.msgNum>=99?'99+':item.msgNum}}</text>
- </view>
- <view class="message_type_pre" @click="goNoticeSet">
- <image :src="setting_icon" mode=""></image>
- <text>{{$L('接收设置')}}</text>
- </view>
- </view>
- </view>
- <!-- 消息类型 end -->
- <!-- 消息列表 start -->
- <view class="message_list">
- <view class="message_list_pre" @touchmove="drawMove" @toucheend="drawEnd"
- :style="{right: (optBtn&&_index==index) ? '240rpx' : '0rpx'}" v-for="(item,index) in chatList" :key="index"
- :data-index="index" @touchstart="drawStart" @click="toDetail(item)">
- <view class="list_pre_left">
- <image :src="item.vendorAvatar" mode="aspectFill"></image>
- </view>
- <view class="list_pre_con">
- <view class="list_pre_top">
- <text class="pre_name">{{item.storeName}}</text>
- <text class="list_pre_time">{{item.addTime}}</text>
- </view>
- <view class="list_pre_bottom">
- <text class="pre_des">{{item.showContent}}</text>
- <text v-if="item.receiveMsgNumber"
- class="list_pre_nums9 list_pre_nums">{{item.receiveMsgNumber>=99?'99+':item.receiveMsgNumber}}</text>
- </view>
- </view>
- <view class="list_pre_btn">
- <text class="list_btn_read" @click.stop="msgReadDone(item.storeId)">{{$L('已读')}}</text>
- <text class="list_btn_del" @click.stop="msgDelete(item.storeId)">{{$L('删除')}}</text>
- </view>
- </view>
- <loadingState v-if="loadingState == 'first_loading'||chatList.length > 0" :state='loadingState' />
- <view class="empty_data" v-if="!chatList.length>0">
- <image :src="imgUrl+'empty_msg.png'" mode=""></image>
- <text>暂无消息记录</text>
- </view>
- </view>
- <!-- 消息列表 end -->
- </view>
- </template>
- <script>
- import loadingState from "@/components/loading-state.vue";
- import {
- mapState,
- mapMutations
- } from 'vuex';
- import io from '@hyoga/uni-socket.io';
- export default {
- components: {
- loadingState
- },
- data() {
- return {
- connectBaseData: {}, //每次通信必传信息
- imgUrl: getApp().globalData.imgUrl,
- assets_news: getApp().globalData.imgUrl + 'member/icon10.png',
- order_news: getApp().globalData.imgUrl + 'member/icon20.png',
- after_sale_news: getApp().globalData.imgUrl + 'member/icon30.png',
- system_news: getApp().globalData.imgUrl + 'member/icon60.png',
- appointment_news: getApp().globalData.imgUrl + 'member/icon70.png',
- setting_icon: getApp().globalData.imgUrl + 'member/receive_settings.png',
- startX: '',
- optBtn: false, //操作按钮是否显示(已读,删除)
- current: 1,
- hasMore: true, //是否还有数据
- pageSize: 10,
- loadingState: 'first_loading',
- chatList: [],
- noticeList: [],
- minMsgId: '', //当前消息的最小id
- socketInfo: '', //socket连接成功返回的房间信息
- _index: '',
- showState: false
- };
- },
- async onLoad() {
- await this.getChatList();
- this.initSocket();
- },
- /**
- * 生命周期函数--监听页面卸载
- */
- onUnload: function() {
- if (this.socket) {
- this.closeSocket();
- }
- },
- computed: {
- ...mapState(['userInfo', 'userCenterData'])
- },
- onBackPress() {
- this.closeSocket();
- },
- onShow() {
- this.getNoticeNum();
- if (this.showState) {
- this.initSocket();
- }
- },
- methods: {
- ...mapMutations(['saveChatBaseInfo']),
- initSocket() {
- if (this.socket) {
- this.closeSocket();
- }
- this.connectBaseData = {
- userId: this.userCenterData.memberId,
- role: 1
- };
- this.socket = io(getApp().globalData.chatUrl, {
- reconnection: true,
- jsonp: true,
- transports: ['websocket', 'polling'],
- timeout: 5000,
- });
- this.socket.on("connect", () => {
- //需要向服务端发送店铺id,方便加入房间
- if (this.chatList.length > 0) {
- this.sendStoreIds();
- }
- //监听最近联系人列表
- this.socket.on("contact_change", e => {
- let tmp_data = this.chatList.filter(item => item.storeId != e.storeId)
- tmp_data.unshift(e);
- this.chatList = tmp_data;
- this.formatMsgContent();
- });
- //监听未读数
- this.socket.on("unread_num_change", e => {
- console.log(e, 'asdasdasdaswesss')
- let tmp_data = this.chatList.filter(item => item.storeId == e.storeId);
- if (tmp_data.length == 1) {
- tmp_data[0].receiveMsgNumber = e.unreadNum;
- }
- });
- });
- },
- // 发送当前列表的所有店铺id
- sendStoreIds() {
- let tmpStoreIdArray = [];
- this.chatList.map(item => {
- tmpStoreIdArray.push(item.storeId);
- });
- this.socket.emit("send_store_ids", {
- storeIds: tmpStoreIdArray.join(','),
- ...this.connectBaseData
- });
- this.socket.emit("connect_success", {
- storeId: '',
- ...this.connectBaseData
- });
- },
- //关闭socket
- closeSocket() {
- if (this.socket) {
- this.socket.close();
- }
- },
- //开始触摸滑动
- drawStart(e) {
- let index = e.currentTarget.dataset.index;
- this._index = index;
- let touch = e.touches[0];
- this.startX = touch.clientX;
- },
- //触摸滑动
- drawMove(e) {
- let touch = e.touches[0];
- let dixX = this.startX - touch.clientX;
- if (dixX >= 20) {
- this.optBtn = true;
- } else {
- this.optBtn = false;
- }
- },
- //触摸滑动结束
- drawEnd(e) {
- this.optBtn = false;
- },
- //去消息设置页面
- goNoticeSet() {
- uni.navigateTo({
- url: '/pages/notice/receivingSet'
- })
- },
- //导航栏跳转页面
- linkTo(tplTypeCode, msgNum) {
- uni.navigateTo({
- url: '/pages/notice/notice?tplType=' + tplTypeCode
- })
- },
- //聊天标记为已读,将未读数置为0
- msgReadDone(storeId) {
- let _this = this;
- this.socket.emit("member_read_all", {
- ...this.connectBaseData
- });
- let tmpData = _this.chatList.filter(item => item.storeId == storeId)[0];
- tmpData.receiveMsgNumber = 0;
- _this.chatList = _this.chatList;
- this.optBtn = false
- },
- //删除聊天
- msgDelete(storeId) {
- let _this = this;
- uni.showModal({
- title: '提示',
- content: '是否删除该聊天?',
- success: res => {
- if (res.confirm) {
- _this.socket.emit("member_remove_contact", {
- storeId: storeId,
- ...this.connectBaseData
- }, () => {
- _this.chatList = _this.chatList.filter(item => item.storeId !=
- storeId);
- });
- _this.optBtn = false;
- _this._index = ''
- }else{
- _this.optBtn = false;
- }
- }
- })
- },
- //获取消息未读数
- getNoticeNum() {
- let param = {}
- param.url = 'v3/msg/front/msg/msgListNum'
- param.method = 'GET'
- this.$request(param).then(res => {
- if (res.state == 200) {
- this.noticeList = res.data;
- } else {
- this.$api.msg(res.msg)
- }
- })
- },
- //获取聊天列表
- async getChatList() {
- let params = {}
- params.url = 'v3/helpdesk/front/chat/storeList',
- params.method = 'GET';
- params.data = {};
- params.data.pageSize = this.pageSize;
- params.data.current = this.current;
- if (this.minMsgId) {
- params.data.msgId = this.minMsgId;
- }
- this.loadingState = this.loadingState == 'first_loading' ? this.loadingState : 'loading';
- await this.$request(params).then(res => {
- if (res.state == 200) {
- if (this.current == 1) {
- this.chatList = res.data
- } else {
- this.chatList = this.chatList.concat(res.data);
- }
- if (this.minMsgId) {
- this.sendStoreIds();
- }
- if (this.chatList.length > 0) {
- this.minMsgId = this.chatList[this.chatList.length - 1].msgId;
- }
- if (res.data.length < this.pageSize) {
- this.hasMore = false;
- }
- if (this.hasMore) {
- this.current++;
- this.loadingState = 'allow_loading_more';
- } else {
- this.loadingState = 'no_more_data';
- }
- this.formatMsgContent();
- } else {
- this.$api.msg(res.msg);
- }
- })
- },
- //格式化聊天内容,方便列表展示
- formatMsgContent() {
- let reg = /<img [^>]*src=['"]([^'"]+)[^>]*>/g
- if (this.chatList.length > 0) {
- this.chatList.map(item => {
- if (typeof item.msgContent == 'string') {
- item.msgContent = JSON.parse(item.msgContent)
- }
- //1.text(文本) 2.img(图片) 3.goods(商品) 4.order(订单)用户
- if (item.msgType == 1) {
- if (reg.test(item.msgContent.content)) {
- item.showContent = item.msgContent.content.replace(reg, '[表情]')
- } else {
- item.showContent = item.msgContent.content;
- }
- } else if (item.msgType == 2) {
- item.showContent = '[图片]';
- } else if (item.msgType == 3) {
- item.showContent = '[商品]';
- } else if (item.msgType == 4) {
- item.showContent = '[订单]';
- }
- })
- }
- },
- onReachBottom() {
- if (this.hasMore) {
- getChatList()
- }
- },
- //前往聊天界面
- toDetail(item) {
- let chatBaseInfo = {};
- chatBaseInfo.memberId = item.memberId;
- chatBaseInfo.memberName = item.memberName;
- chatBaseInfo.memberNickName = item.memberName;
- chatBaseInfo.memberAvatar = item.memberAvatar;
- chatBaseInfo.storeId = item.storeId;
- chatBaseInfo.storeLogo = item.vendorAvatar;
- chatBaseInfo.storeName = item.storeName;
- chatBaseInfo.source = 'chat_list';
- chatBaseInfo.showData = {}
- this.saveChatBaseInfo(chatBaseInfo);
- this.showState = true
- uni.navigateTo({
- url: '/pages/chat/detail?vid=' + item.storeId
- })
- }
- },
- }
- </script>
- <style lang='scss'>
- page {
- background: #FFFFFF;
- }
- .message_center {
- width: 750rpx;
- margin-left: calc((100vw - 750rpx) / 2);
- /* 消息类型 start */
- .message_type {
- padding: 32rpx 20rpx 20rpx;
- border-top: 1rpx solid #F2F2F2;
- display: flex;
- overflow-x: scroll;
- .message_type_con {
- padding-right: 20rpx;
- display: flex;
- .message_type_pre {
- margin-right: 40rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- position: relative;
- image {
- width: 70rpx;
- height: 70rpx;
- }
- text {
- font-size: 28rpx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #2D2D2D;
- line-height: 32rpx;
- margin-top: 20rpx;
- white-space: nowrap;
- }
- .message_type_nums {
- position: absolute;
- right: 18rpx;
- top: -28rpx;
- min-width: 22rpx;
- height: 22rpx;
- background: #FF0000;
- border-radius: 13rpx;
- font-size: 20rpx;
- font-family: PingFang SC;
- font-weight: 400;
- color: #FFFFFF;
- line-height: 22rpx;
- text-align: center;
- }
- .message_type_nums_9 {
- padding: 0 5rpx;
- /* height: 22rpx; */
- }
- }
- .message_type_pre:nth-last-of-type(1) {
- margin-right: 0;
- }
- }
- }
- /* 消息类型 end */
- /* 消息列表 start */
- .message_list {
- border-top: 20rpx solid #F5F5F5;
- overflow-x: hidden;
- .message_list_pre {
- display: flex;
- align-items: center;
- margin: 0 20rpx;
- border-bottom: 1rpx solid #F2F2F2;
- height: 150rpx;
- position: relative;
- transition: all 0.3s;
- .message_list_pre:last-child {
- border: none;
- }
- .list_pre_left {
- width: 80rpx;
- height: 80rpx;
- border-radius: 50%;
- margin-right: 30rpx;
- image {
- width: 80rpx;
- height: 80rpx;
- border-radius: 50%;
- }
- }
- .list_pre_con {
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- align-items: space-between;
- width: 620rpx;
- padding: 40rpx 0;
- height: 150rpx;
- box-sizing: border-box;
- .list_pre_top {
- display: flex;
- justify-content: space-between;
- .pre_name {
- font-size: 30rpx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #333333;
- line-height: 30rpx;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .list_pre_time {
- font-size: 22rpx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #999999;
- line-height: 32rpx;
- }
- }
- .list_pre_bottom {
- display: flex;
- justify-content: space-between;
- .pre_des {
- width: 484rpx;
- font-size: 26rpx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #999999;
- line-height: 28rpx;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- height: 30rpx;
- }
- .list_pre_nums {
- height: 22rpx;
- background: #FF0000;
- border-radius: 10rpx;
- text-align: center;
- line-height: 22rpx;
- font-size: 20rpx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #FFFFFF;
- line-height: 22rpx;
- }
- .list_pre_nums9 {
- position: absolute;
- left: 48rpx;
- top: 24rpx;
- padding: 0 4rpx;
- min-width: 22rpx;
- }
- }
- }
- .list_pre_btn {
- display: flex;
- align-items: center;
- position: absolute;
- top: 0;
- right: -260rpx;
- .list_btn_read {
- width: 120rpx;
- height: 150rpx;
- background: #EEEEEE;
- font-size: 28rpx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #333333;
- line-height: 150rpx;
- text-align: center;
- }
- .list_btn_del {
- width: 120rpx;
- height: 150rpx;
- background: #FF0000;
- font-size: 28rpx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #FFFFFF;
- line-height: 150rpx;
- text-align: center;
- }
- }
- }
- }
- /* 消息列表 end */
- }
- .empty_data {
- height: 750rpx;
- display: flex;
- justify-content: center;
- flex-direction: column;
- align-items: center;
- image {
- width: 200rpx;
- height: 200rpx;
- }
- text {
- margin-top: 20rpx;
- font-size: 28rpx;
- color: #999999;
- }
- }
- </style>
|