| 1 |
- {"remainingRequest":"D:\\front\\item\\zyAdmin\\node_modules\\vue-loader\\lib\\index.js??vue-loader-options!D:\\front\\item\\zyAdmin\\src\\pages\\kefu\\mobile\\chat_list.vue?vue&type=style&index=0&id=3e277eca&lang=css","dependencies":[{"path":"D:\\front\\item\\zyAdmin\\src\\pages\\kefu\\mobile\\chat_list.vue","mtime":1761614939021},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\css-loader\\index.js","mtime":1761614929364},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\vue-loader\\lib\\loaders\\stylePostLoader.js","mtime":1761614937403},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\postcss-loader\\src\\index.js","mtime":1761614935133},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\cache-loader\\dist\\cjs.js","mtime":1761614927801},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\vue-loader\\lib\\index.js","mtime":1761614937402}],"contextDependencies":[],"result":[{"type":"Buffer","data":"base64:DQpodG1sLA0KYm9keSB7DQogIGZvbnQtc2l6ZTogNTBweDsNCn0NCg=="},{"version":3,"sources":["chat_list.vue"],"names":[],"mappings":";AAgVA;AACA;AACA;AACA","file":"chat_list.vue","sourceRoot":"src/pages/kefu/mobile","sourcesContent":["<template>\r\n <div class=\"chat-list\">\r\n <div class=\"head-box\">\r\n <div class=\"hd\">\r\n <div class=\"left-wrappers\">\r\n <img v-lazy=\"kefuInfo.avatar\" />\r\n <div class=\"info\" v-db-click @click=\"isOnLine = !isOnLine\">\r\n <div>{{ kefuInfo.nickname }}</div>\r\n <div class=\"status\">\r\n <span class=\"doc\" :class=\"{ off: !kefuInfo.online }\"></span>\r\n <span>{{ kefuInfo.online ? '在线' : '离线' }}</span>\r\n </div>\r\n </div>\r\n <div class=\"down-wrapper\" v-show=\"isOnLine\">\r\n <div class=\"item\" v-db-click @click=\"changOnline(1)\">\r\n <span class=\"dot green\"></span>在线\r\n <span class=\"iconfont iconduihao\" v-if=\"kefuInfo.online\"></span>\r\n </div>\r\n <div class=\"item\" v-db-click @click=\"changOnline(0)\">\r\n <span class=\"dot\"></span>离线\r\n <span class=\"iconfont iconduihao\" v-if=\"!kefuInfo.online\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"right-wrapper\" v-db-click @click=\"outLogin\">\r\n <div class=\"icon-box\"><span class=\"iconfont icontuichu\"></span></div>\r\n\r\n <div style=\"margin-left: 5px\">退出登录</div>\r\n </div>\r\n </div>\r\n <div class=\"tab-box\">\r\n <div\r\n class=\"tab-item\"\r\n :class=\"{ on: tabCur == item.key }\"\r\n v-for=\"(item, index) in tabList\"\r\n v-db-click\r\n @click=\"changeClass(item)\"\r\n >\r\n {{ item.title }}\r\n </div>\r\n </div>\r\n <div class=\"search-box\">\r\n <el-input v-model=\"searchTxt\" placeholder=\"搜索用户名称\" @change=\"bindSearch\" />\r\n </div>\r\n </div>\r\n <div class=\"list-box\" v-if=\"list.length > 0\">\r\n <vue-scroll ref=\"vs\" :ops=\"ops\" @load-before-deactivate=\"handleBeforeDeactivate\">\r\n <div class=\"item\" v-for=\"(item, index) in list\" :key=\"index\" v-db-click @click=\"goPage(item)\">\r\n <div class=\"left-wrappers\">\r\n <div class=\"img-box\">\r\n <img v-lazy=\"item.avatar\" />\r\n <div class=\"online\" :class=\"{ on: item.online }\"></div>\r\n </div>\r\n <div class=\"info\">\r\n <div class=\"title\">\r\n <span class=\"line1\">{{ item.nickname }}</span>\r\n <template v-if=\"item.type == 2\">\r\n <span class=\"label\">小程序</span>\r\n </template>\r\n <template v-if=\"item.type == 3\">\r\n <span class=\"label h5\">H5</span>\r\n </template>\r\n <template v-if=\"item.type == 1\">\r\n <span class=\"label wx\">公众号</span>\r\n </template>\r\n <template v-if=\"item.type == 0\">\r\n <span class=\"label pc\">PC端</span>\r\n </template>\r\n </div>\r\n <div class=\"msg line1\" v-if=\"item.message_type == 1\">{{ item.message }}</div>\r\n <div class=\"msg\" v-if=\"item.message_type == 2\">[表情]</div>\r\n <div class=\"msg\" v-if=\"item.message_type == 3\">[图片]</div>\r\n <div class=\"msg\" v-if=\"item.message_type == 5\">[商品]</div>\r\n <div class=\"msg\" v-if=\"item.message_type == 6\">[订单]</div>\r\n </div>\r\n </div>\r\n <div class=\"right-wrapper\">\r\n <div class=\"time\">{{ item.update_time | toDay }}</div>\r\n <span class=\"num\" v-if=\"item.mssage_num > 0\">{{ item.mssage_num }}</span>\r\n </div>\r\n </div>\r\n <div class=\"slot-load\" slot=\"load-deactive\"></div>\r\n <div class=\"slot-load\" slot=\"load-active\">下滑加载更多</div>\r\n </vue-scroll>\r\n </div>\r\n <empty v-else status=\"3\" msg=\"暂无用户列表\"></empty>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport util from '@/libs/util';\r\nimport { Socket } from '@/libs/socket';\r\nimport { record } from '@/api/kefu.js';\r\nimport { serviceInfo } from '@/api/kefu_mobile';\r\nimport { HappyScroll } from 'vue-happy-scroll';\r\nimport { mapState, mapActions } from 'vuex';\r\nimport { getCookies } from '@/libs/util';\r\nimport empty from '../components/empty';\r\nvar mp3 = require('@/assets/video/notice.mp3');\r\nvar mp3 = new Audio(mp3);\r\nexport default {\r\n name: 'chat_list.vue',\r\n components: {\r\n HappyScroll,\r\n empty,\r\n },\r\n data() {\r\n return {\r\n ops: {\r\n vuescroll: {\r\n mode: 'slide',\r\n enable: false,\r\n tips: {\r\n deactive: 'Push to Load',\r\n active: 'Release to Load',\r\n start: 'Loading...',\r\n beforeDeactive: 'Load Successfully!',\r\n },\r\n auto: false,\r\n autoLoadDistance: 0,\r\n pullRefresh: {\r\n enable: false,\r\n },\r\n pushLoad: {\r\n enable: true,\r\n auto: true,\r\n autoLoadDistance: 10,\r\n },\r\n },\r\n bar: {\r\n background: '#393232',\r\n opacity: '.5',\r\n size: '2px',\r\n },\r\n },\r\n list: [],\r\n page: 1,\r\n limit: 15,\r\n isScroll: true,\r\n searchTxt: '',\r\n isOpen: true,\r\n kefuInfo: {},\r\n isOnLine: false,\r\n tabCur: 0,\r\n tabList: [\r\n {\r\n key: 0,\r\n title: '用户列表',\r\n },\r\n ],\r\n wsLogin: JSON.parse(sessionStorage.getItem('wsLogin')),\r\n };\r\n },\r\n filters: {\r\n toDay: function (value) {\r\n if (!value) return '';\r\n var date = new Date(); //时间戳为10位需*1000,时间戳为13位的话不需乘1000\r\n var Y = date.getFullYear() + '-';\r\n var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';\r\n var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';\r\n var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';\r\n var m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();\r\n var s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();\r\n\r\n value = M + D + h + m;\r\n return value;\r\n },\r\n },\r\n created() {\r\n Promise.all([this.getKefuInfo(), this.getList()]);\r\n },\r\n mounted() {\r\n let that = this;\r\n // 监听页面刷新\r\n window.addEventListener('beforeunload', (e) => {\r\n sessionStorage.setItem('wsLogin', false);\r\n });\r\n // 获取是否登录的key\r\n this.wsLogin = JSON.parse(sessionStorage.getItem('wsLogin'));\r\n let token = getCookies('kefu_token');\r\n Socket.then((ws) => {\r\n if (!that.wsLogin && token) {\r\n ws.send({\r\n type: 'kefu_login',\r\n data: getCookies('kefu_token'),\r\n });\r\n }\r\n //用户未读消息条数更改\r\n ws.$on('transfer', (data) => {\r\n if (data.recored.id) {\r\n let status = false;\r\n for (let i = 0; i < this.list.length; i++) {\r\n if (data.recored.id == this.list[i].id) {\r\n status = true;\r\n this.$set(this.list, i, data.recored);\r\n }\r\n }\r\n if (!status) {\r\n this.list.unshift(data.recored);\r\n }\r\n }\r\n });\r\n ws.$on('mssage_num', (data) => {\r\n if (data.num > 0) {\r\n mp3.play();\r\n }\r\n if (data.recored.id) {\r\n let status = false;\r\n // for(let i =0 ;i<this.list.length;i++){\r\n // if(data.recored.id == this.list[i].id){\r\n // status = true\r\n // this.$set(this.list, i, data.recored)\r\n // break\r\n // }\r\n // }\r\n that.list.forEach((el, index, arr) => {\r\n if (data.recored.id == el.id) {\r\n status = true;\r\n if (data.recored.is_tourist == that.tabCur) {\r\n let oldVal = data.recored;\r\n arr.splice(index, 1);\r\n arr.unshift(oldVal);\r\n }\r\n }\r\n });\r\n if (!status) {\r\n if (data.recored.is_tourist == this.tabCur) this.list.unshift(data.recored);\r\n }\r\n if (data.recored.is_tourist != this.tabCur && data.recored.id) {\r\n this.$notify.info({\r\n title: this.tabCur ? '用户发来消息啦!' : '游客发来消息啦!',\r\n });\r\n }\r\n }\r\n });\r\n // ws登录成功\r\n ws.$on('success', (data) => {\r\n sessionStorage.setItem('wsLogin', true);\r\n });\r\n });\r\n },\r\n beforeDestroy() {},\r\n methods: {\r\n ...mapActions('kefu/', ['logout', 'logoutKefu']),\r\n // 列表切换\r\n changeClass(item) {\r\n if (this.tabCur == item.key) return;\r\n this.tabCur = item.key;\r\n this.page = 1;\r\n this.list = [];\r\n this.isScroll = true;\r\n this.getList();\r\n },\r\n // 客服上下线\r\n changOnline(key) {\r\n this.kefuInfo.online = key;\r\n this.isOnLine = false;\r\n Socket.then((ws) => {\r\n let that = this;\r\n ws.send({\r\n type: 'online',\r\n data: {\r\n online: key,\r\n },\r\n });\r\n });\r\n },\r\n // 客服详细信息\r\n getKefuInfo() {\r\n serviceInfo().then((res) => {\r\n this.kefuInfo = res.data;\r\n window.document.title = `${res.data.site_name} - 消息列表`;\r\n });\r\n },\r\n getList() {\r\n if (!this.isScroll) return;\r\n record({\r\n nickname: this.searchTxt,\r\n page: this.page,\r\n limit: this.limit,\r\n is_tourist: this.tabCur,\r\n }).then((res) => {\r\n this.isScroll = res.data.length >= this.limit;\r\n this.list = this.list.concat(res.data);\r\n this.page++;\r\n setTimeout(() => {\r\n this.$refs.vs.refresh();\r\n }, 100);\r\n });\r\n },\r\n // 客服退出\r\n outLogin() {\r\n let self = this;\r\n this.$msgbox({\r\n title: '退出登录确认',\r\n message: '您确定退出登录当前账户吗?打开的标签页和个人设置将会保存。',\r\n showCancelButton: true,\r\n cancelButtonText: '取消',\r\n confirmButtonText: '确定',\r\n iconClass: 'el-icon-warning',\r\n confirmButtonClass: 'btn-custom-cancel',\r\n })\r\n .then(() => {\r\n self.logoutKefu({\r\n confirm: false,\r\n vm: self,\r\n });\r\n })\r\n .catch(() => {});\r\n },\r\n // 搜索\r\n bindSearch(e) {\r\n this.page = 1;\r\n this.list = [];\r\n this.isScroll = true;\r\n this.getList();\r\n },\r\n // 进入对话\r\n goPage(item) {\r\n this.$router.push({\r\n path: 'mobile_chat',\r\n query: {\r\n toUid: item.to_uid,\r\n nickname: item.nickname,\r\n is_tourist: this.tabCur,\r\n },\r\n });\r\n },\r\n handleBeforeDeactivate(vm, refreshDom, done) {\r\n this.getList();\r\n done();\r\n },\r\n },\r\n};\r\n</script>\r\n<style>\r\nhtml,\r\nbody {\r\n font-size: 50px;\r\n}\r\n</style>\r\n<style lang=\"scss\" scoped>\r\n.chat-list {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n padding-bottom: 0.15rem;\r\n background: #fff;\r\n .head-box {\r\n .hd {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n height: 1rem;\r\n padding: 0 0.3rem;\r\n background: linear-gradient(90deg, #3875ea 0%, #1890fc 100%);\r\n .left-wrappers {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n color: #fff;\r\n font-size: 0.26rem;\r\n\r\n img {\r\n width: 0.58rem;\r\n height: 0.58rem;\r\n border-radius: 50%;\r\n }\r\n .info {\r\n margin-left: 0.12rem;\r\n .status {\r\n display: flex;\r\n align-items: center;\r\n font-size: 0.2rem;\r\n .doc {\r\n width: 0.14rem;\r\n height: 0.14rem;\r\n margin-right: 0.1rem;\r\n background-color: #27f2cb;\r\n border-radius: 50%;\r\n margin-top: 0.04rem;\r\n &.off {\r\n background: #919191;\r\n }\r\n }\r\n }\r\n }\r\n .down-wrapper {\r\n z-index: 50;\r\n position: absolute;\r\n left: 0;\r\n bottom: -1.9rem;\r\n width: 2.14rem;\r\n background: #434343;\r\n border-radius: 0.1rem;\r\n .item {\r\n display: flex;\r\n align-items: center;\r\n height: 0.8rem;\r\n padding-left: 0.3rem;\r\n border-bottom: 1px solid rgba(240, 241, 242, 0.16);\r\n font-size: 0.28rem;\r\n &:last-child {\r\n border-bottom: none;\r\n }\r\n .dot {\r\n width: 0.12rem;\r\n height: 0.12rem;\r\n margin-right: 0.16rem;\r\n border-radius: 50%;\r\n background: linear-gradient(180deg, #bcbcbc 0%, #919191 100%);\r\n &.green {\r\n background: linear-gradient(143deg, #27f2cb 0%, #14e3b4 100%);\r\n }\r\n }\r\n .iconfont {\r\n margin-left: 0.36rem;\r\n color: #b9b9b9;\r\n font-size: 0.18rem;\r\n }\r\n }\r\n }\r\n }\r\n .right-wrapper {\r\n display: flex;\r\n align-items: center;\r\n color: #fff;\r\n font-size: 0.24rem;\r\n }\r\n }\r\n .search-box {\r\n padding: 0 0.3rem 0.2rem;\r\n border-bottom: 1px solid #eceff8;\r\n ::v-deep .ivu-input {\r\n display: block;\r\n width: 100%;\r\n height: 0.68rem;\r\n background: #f5f6f9;\r\n border-radius: 0.39rem;\r\n box-sizing: border-box;\r\n font-size: 0.28rem;\r\n border-radius: 0.39rem;\r\n text-align: center;\r\n }\r\n ::v-deep .ivu-input,\r\n .ivu-input:hover,\r\n .ivu-input:focus {\r\n border: transparent;\r\n box-shadow: none;\r\n }\r\n }\r\n .tab-box {\r\n display: flex;\r\n padding: 0.2rem 0;\r\n .tab-item {\r\n flex: 1;\r\n height: 100%;\r\n line-height: 0.6rem;\r\n text-align: center;\r\n font-size: 0.3rem;\r\n &.on {\r\n color: #3875ea;\r\n }\r\n &:first-child {\r\n border-right: 1px solid #ddd;\r\n }\r\n }\r\n }\r\n }\r\n .list-box {\r\n flex: 1;\r\n overflow: hidden;\r\n .item {\r\n display: flex;\r\n justify-content: space-between;\r\n padding: 0.23rem 0.3rem;\r\n height: 1.5rem;\r\n .left-wrappers {\r\n display: flex;\r\n align-items: center;\r\n .img-box {\r\n width: 0.96rem;\r\n height: 0.96rem;\r\n position: relative;\r\n }\r\n .online {\r\n position: absolute;\r\n right: 0.1rem;\r\n bottom: 1px;\r\n width: 0.16rem;\r\n height: 0.16rem;\r\n background: linear-gradient(143deg, #bcbcbc 0%, #919191 100%);\r\n border-radius: 50%;\r\n border: 1px solid #ffffff;\r\n &.on {\r\n background: linear-gradient(143deg, #27f2cb 0%, #14e3b4 100%);\r\n }\r\n }\r\n img {\r\n width: 0.96rem;\r\n height: 0.96rem;\r\n border-radius: 50%;\r\n }\r\n .info {\r\n margin-left: 0.2rem;\r\n width: 3.5rem;\r\n height: 0.96rem;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: space-between;\r\n .title {\r\n display: flex;\r\n align-items: center;\r\n font-size: 0.3rem;\r\n .label {\r\n margin-left: 0.15rem;\r\n font-size: 0.2rem;\r\n padding: 0.05rem 0.1rem;\r\n background: rgba(56, 117, 234, 0.14);\r\n color: #3875ea;\r\n border-radius: 0.04rem;\r\n &.h5 {\r\n background: rgba(255, 162, 0, 0.18);\r\n color: #d08800;\r\n }\r\n &.wx {\r\n background: rgba(0, 186, 100, 0.14);\r\n color: #00a219;\r\n }\r\n &.pc {\r\n background: rgba(133, 64, 227, 0.14);\r\n color: #820adb;\r\n }\r\n }\r\n }\r\n .msg {\r\n font-size: 0.24rem;\r\n color: #9f9f9f;\r\n }\r\n }\r\n }\r\n .right-wrapper {\r\n height: 0.96rem;\r\n color: #9f9f9f;\r\n font-size: 0.22rem;\r\n text-align: right;\r\n .num {\r\n min-width: 0.12rem;\r\n background-color: #f74c31;\r\n color: #fff;\r\n border-radius: 0.15rem;\r\n right: 0 rpx;\r\n bottom: 0 rpx;\r\n font-size: 0.2rem;\r\n padding: 0 0.08rem;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n</style>\r\n"]}]}
|