From 25b2ba1cf86bc3439e7ad2acf2cd4a9ea7e4b0ed Mon Sep 17 00:00:00 2001
From: dcc <dcc@163.com>
Date: Fri, 28 Jun 2024 09:28:04 +0800
Subject: [PATCH] 123
---
src/page/customerService/index.vue | 542 +++++++++++++++++++++++++++++++-----------------------
1 files changed, 310 insertions(+), 232 deletions(-)
diff --git a/src/page/customerService/index.vue b/src/page/customerService/index.vue
index 95b1991..ba8ce0e 100644
--- a/src/page/customerService/index.vue
+++ b/src/page/customerService/index.vue
@@ -1,284 +1,362 @@
<template>
- <div class="service-box pb-150 flex flex-col">
- <van-nav-bar :title="$t('在线客服')" left-arrow @click-left="onClickLeft" fixed />
- <div class="flex-1" v-if="kefu_url">
- <iframe :src="kefu_url" width="100%" height="100%" frameborder="0"></iframe>
- </div>
- <div v-else class="localKefu flex-1 flex">
- <div class="flex flex-col px-32 box-border flex-1" ref="boxScroll" style="overflow:auto;">
- <div class="w-full py-10 text-grey text-center pt-10" @click="onMore"
- :style="{ 'visibility': finished ? 'hidden' : 'visiable' }">
- {{ $t('历史消息') }}</div>
- <ul class="flex flex-col pt-20">
- <li v-for="(item, index) in list" :key="item.id" class="flex flex-col mt-20"
- v-if="item.delete_status == 0">
- <p class="font-26 text-center py-20 text-grey">
- {{ item.createtime }}</p>
- <div class="flex" :class="item.send_receive === 'send' ? 'justify-end' : ''">
- <template v-if="item.send_receive === 'receive'">
- <img src="@/assets/image/assets-center/logo.png" class="w-81 h-81 mr-40" />
- <div class="responser px-50 py-35 font-30 rounded-lg font-26 chatBg">
- <p class="break-word textColor" style="max-width: 230px;" v-if="item.type === 'text'">
- {{ item.content }}</p>
- <img v-else :src="item.content" class="w-200 h-200" @click="onPreview(item.content)" />
- </div>
- </template>
- <div class="py-25 px-50 responser-two rounded-lg flex flex-col chatBg" v-else>
- <img :src="`${item.content}`" class="w-200 h-200" v-if="item.type === 'img'"
- @click="onPreview(item.content)" />
- <p class="break-word textColor" v-else style="max-width: 230px;">{{ item.content }}
- </p>
- </div>
- </div>
- </li>
- </ul>
- </div>
- <div
- class="bottom flex justify-between h-130 items-center w-full fixed bottom-0 borderTop px-32 box-border bgBottom">
- <van-uploader :max-size="10000 * 1024" @oversize="onOversize" :after-read="afterRead">
- <img src="@/assets/image/service/photo.png" class="w-72 h-72" />
- </van-uploader>
- <input type="text" v-model="value" :placeholder="$t('请输入您的消息...')"
- class="flex-1 mx-20 h-full border-none bgBottom textColor" />
- <img src="@/assets/image/service/send.png" class="w-72 h-72" @click="send('text', value)" />
- </div>
- </div>
+ <div class="service-box pb-150 flex flex-col">
+ <van-nav-bar
+ :title="$t('在线客服')"
+ left-arrow
+ @click-left="onClickLeft"
+ fixed
+ />
+ <div class="flex-1" v-if="kefu_url">
+ <iframe
+ :src="kefu_url"
+ width="100%"
+ height="100%"
+ frameborder="0"
+ ></iframe>
</div>
+ <div v-else class="localKefu flex-1 flex">
+ <div
+ class="flex flex-col px-32 box-border flex-1"
+ ref="boxScroll"
+ style="overflow: auto"
+ >
+ <div
+ class="w-full py-10 text-grey text-center pt-10"
+ @click="onMore"
+ :style="{ visibility: finished ? 'hidden' : 'visiable' }"
+ >
+ {{ $t("历史消息") }}
+ </div>
+ <ul class="flex flex-col pt-20">
+ <li
+ v-for="(item, index) in list"
+ :key="item.id"
+ class="flex flex-col mt-20"
+ v-if="item.delete_status == 0"
+ >
+ <p class="font-26 text-center py-20 text-grey">
+ {{ item.createtime }}
+ </p>
+ <div
+ class="flex"
+ :class="item.send_receive === 'send' ? 'justify-end' : ''"
+ >
+ <template v-if="item.send_receive === 'receive'">
+ <img
+ src="@/assets/image/assets-center/logo.png"
+ class="w-81 h-81 mr-40"
+ />
+ <div
+ class="responser px-50 py-35 font-30 rounded-lg font-26 chatBg"
+ >
+ <p
+ class="break-word textColor"
+ style="max-width: 230px"
+ v-if="item.type === 'text'"
+ >
+ {{ item.content }}
+ </p>
+ <img
+ v-else
+ :src="item.content"
+ class="w-200 h-200"
+ @click="onPreview(item.content)"
+ />
+ </div>
+ </template>
+ <div
+ class="py-25 px-50 responser-two rounded-lg flex flex-col chatBg"
+ v-else
+ >
+ <img
+ :src="`${item.content}`"
+ class="w-200 h-200"
+ v-if="item.type === 'img'"
+ @click="onPreview(item.content)"
+ />
+ <p class="break-word textColor" v-else style="max-width: 230px">
+ {{ item.content }}
+ </p>
+ </div>
+ </div>
+ </li>
+ </ul>
+ </div>
+ <div
+ class="bottom flex justify-between h-130 items-center w-full fixed bottom-0 borderTop px-32 box-border bgBottom"
+ >
+ <van-uploader
+ :max-size="10000 * 1024"
+ @oversize="onOversize"
+ :after-read="afterRead"
+ >
+ <img src="@/assets/image/service/photo.png" class="w-72 h-72" />
+ </van-uploader>
+ <input
+ type="text"
+ v-model="value"
+ :placeholder="$t('请输入您的消息...')"
+ class="flex-1 mx-20 h-full border-none bgBottom textColor"
+ />
+ <span @click="send('text', value)">
+ <img src="@/assets/image/service/send.png" class="w-72 h-72" />
+ </span>
+ </div>
+ </div>
+ </div>
</template>
<script>
import { mapGetters } from "vuex";
-import { _getMsg, _getUnreadMsg, _sendMsg } from '@/API/im.api'
-import { _uploadImage } from '@/API/fund.api'
-import { Uploader, ImagePreview } from 'vant'
+import { _getMsg, _getUnreadMsg, _sendMsg } from "@/API/im.api";
+import { _uploadImage } from "@/API/fund.api";
+import { Uploader, ImagePreview } from "vant";
export default {
- name: 'CustomerService',
- components: {
- [Uploader.name]: Uploader
+ name: "CustomerService",
+ components: {
+ [Uploader.name]: Uploader,
+ },
+ data() {
+ return {
+ list: [],
+ value: "",
+ lastMsgId: "",
+ interval: null,
+ unread: 0,
+ finished: false, // 没有历史消息
+ currentScrollTop: 0,
+ isScrollBottom: false,
+ };
+ },
+ computed: {
+ ...mapGetters("home", ["kefu_url"]),
+ },
+ created() {
+ this.fetchList();
+ },
+ mounted() {
+ window.addEventListener("scroll", this.handleScroll, true);
+ },
+ methods: {
+ onOversize(file) {
+ console.log(file);
+ this.$toast(this.$t("文件大小不能超过10m"));
},
- data() {
- return {
- list: [],
- value: '',
- lastMsgId: '',
- interval: null,
- unread: 0,
- finished: false, // 没有历史消息
- currentScrollTop: 0,
- isScrollBottom: false
+ onPreview(url) {
+ // 预览
+ ImagePreview([url]);
+ },
+ showTime(index) {
+ // 时间显示
+ if (index === 0) {
+ return true;
+ }
+ if (index === this.list.length - 1) {
+ return false;
+ }
+ if (
+ this.list[index].createtime.split(" ")[0] ===
+ this.list[index + 1].createtime.split(" ")[1]
+ ) {
+ return false;
+ }
+ },
+ afterRead(file) {
+ // 文件上传
+ this.$toast.loading({ duration: 0 });
+ _uploadImage(file, (percent) => {
+ console.log(percent);
+ })
+ .then((data) => {
+ this.$toast.clear();
+ this.send("img", data);
+ })
+ .catch(() => {
+ this.$toast.clear();
+ file.status = "failed";
+ file.message = this.$t("图片上传失败");
+ });
+ },
+ fetchList(message_id = "") {
+ // 获取消息列表
+ _getMsg({ message_id }).then((data) => {
+ // this.lastMsgId
+ if (!this.lastMsgId) {
+ this.lastMsgId = data.length && data[data.length - 1]["id"];
}
- },
- computed: {
- ...mapGetters('home', ['kefu_url'])
- },
- created() {
- this.fetchList()
- },
- mounted() {
- window.addEventListener('scroll', this.handleScroll, true)
- },
- methods: {
- onOversize(file) {
- console.log(file);
- this.$toast(this.$t('文件大小不能超过10m'));
- },
- onPreview(url) { // 预览
- ImagePreview([url])
- },
- showTime(index) { // 时间显示
- if (index === 0) {
- return true
- }
- if (index === this.list.length - 1) {
- return false
- }
- if (this.list[index].createtime.split(' ')[0] === this.list[index + 1].createtime.split(' ')[1]) {
- return false
- }
- },
- afterRead(file) { // 文件上传
- this.$toast.loading({ duration: 0 })
- _uploadImage(file, (percent) => {
- console.log(percent)
- }).then(data => {
- this.$toast.clear()
- this.send('img', data)
- }).catch(() => {
- this.$toast.clear();
- file.status = 'failed';
- file.message = this.$t('图片上传失败');
- })
- },
- fetchList(message_id = '') { // 获取消息列表
- _getMsg({ message_id }).then(data => { // this.lastMsgId
- if (!this.lastMsgId) {
- this.lastMsgId = data.length && data[data.length - 1]['id']
- }
- if (data.length) {
- if (message_id) { // 加载更多
- this.lastMsgId = data[data.length - 1]['id']
- this.list = [...data.reverse(), ...this.list]
- } else {
- let list = [...this.list, ...data.reverse()]
- let hash = {};
- list = list.reverse().reduce(function (preVal, curVal) {
- hash[curVal.id] ? ' ' : hash[curVal.id] = true && preVal.push(curVal);
- return preVal
- }, []);
- this.list = list.reverse()
- }
- if (this.isScrollBottom) {
- this.$refs.boxScroll.scrollTop = this.$refs.boxScroll.scrollHeight - this.$refs.boxScroll.offsetHeight
- }
- this.currentScrollTop = this.$refs.boxScroll.scrollTop;
- if (data.length < 10) {
- this.finished = true
- }
- }
-
- // else {
- // this.list = [{ id: '1', send_receive: 'receive', content: this.$t('你好,欢迎来到我们的数字货币平台!'), type: 'text'}]
- // }
- if (!message_id) {
- this.clearInterval()
- this.interval = setInterval(() => {
- this.fetchList()
- }, 1000)
- }
- })
- },
- handleScroll() {
- if (this.$refs.boxScroll.scrollTop == this.currentScrollTop) {
- this.isScrollBottom = true
- } else {
- this.isScrollBottom = false
- }
- },
- onMore() { // 加载更多
- this.fetchList(this.lastMsgId)
- },
- clearInterval() {
- if (this.interval) {
- clearInterval(this.interval)
- this.interval = null
- }
- },
- fetchUnread() { // 获取未读
- _getUnreadMsg().then(data => {
- this.unread = data
- })
- },
- onClickLeft() { // 返回
- this.$router.go(-1);
- },
- send(type = 'text', content = '') { // 发送消息, img 也当消息text
- if (!content) {
- this.$toast(this.$t('请输入消息内容'))
- return
- }
- _sendMsg(type, content).then(data => {
- console.log(data)
- this.isScrollBottom = true
- this.value = ''
- // document.getElementById('bottom').click()
- })
+ if (data.length) {
+ if (message_id) {
+ // 加载更多
+ this.lastMsgId = data[data.length - 1]["id"];
+ this.list = [...data.reverse(), ...this.list];
+ } else {
+ let list = [...this.list, ...data.reverse()];
+ let hash = {};
+ list = list.reverse().reduce(function (preVal, curVal) {
+ hash[curVal.id]
+ ? " "
+ : (hash[curVal.id] = true && preVal.push(curVal));
+ return preVal;
+ }, []);
+ this.list = list.reverse();
+ }
+ if (this.isScrollBottom) {
+ this.$refs.boxScroll.scrollTop =
+ this.$refs.boxScroll.scrollHeight -
+ this.$refs.boxScroll.offsetHeight;
+ }
+ this.currentScrollTop = this.$refs.boxScroll.scrollTop;
+ if (data.length < 10) {
+ this.finished = true;
+ }
}
+ // else {
+ // this.list = [{ id: '1', send_receive: 'receive', content: this.$t('你好,欢迎来到我们的数字货币平台!'), type: 'text'}]
+ // }
+ if (!message_id) {
+ this.clearInterval();
+ this.interval = setInterval(() => {
+ this.fetchList();
+ }, 1000);
+ }
+ });
},
- beforeDestroy() {
- this.clearInterval()
+ handleScroll() {
+ if (this.$refs.boxScroll.scrollTop == this.currentScrollTop) {
+ this.isScrollBottom = true;
+ } else {
+ this.isScrollBottom = false;
+ }
},
- activated() {
- window.addEventListener('scroll', this.handleScroll, true)
+ onMore() {
+ // 加载更多
+ this.fetchList(this.lastMsgId);
},
- deactivated() {
- this.clearInterval()
- window.removeEventListener('scroll', this.handleScroll)
+ clearInterval() {
+ if (this.interval) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
},
- destroyed() {
- window.removeEventListener('scroll', this.handleScroll)
- }
-}
+ fetchUnread() {
+ // 获取未读
+ _getUnreadMsg().then((data) => {
+ this.unread = data;
+ });
+ },
+ onClickLeft() {
+ // 返回
+ this.$router.go(-1);
+ },
+ send(type = "text", content = "") {
+ // 发送消息, img 也当消息text
+ if (!content) {
+ this.$toast(this.$t("请输入消息内容"));
+ return;
+ }
+ _sendMsg(type, content).then((data) => {
+ console.log(data);
+ this.isScrollBottom = true;
+ this.value = "";
+ // document.getElementById('bottom').click()
+ });
+ },
+ },
+ beforeDestroy() {
+ this.clearInterval();
+ },
+ activated() {
+ window.addEventListener("scroll", this.handleScroll, true);
+ },
+ deactivated() {
+ this.clearInterval();
+ window.removeEventListener("scroll", this.handleScroll);
+ },
+ destroyed() {
+ window.removeEventListener("scroll", this.handleScroll);
+ },
+};
</script>
<style lang="scss" scoped>
.service-box {
- width: 100%;
- height: 100%;
- box-sizing: border-box;
+ width: 100%;
+ height: 100%;
+ box-sizing: border-box;
- ::v-deep .van-hairline--bottom::after {
- @include themify() {
- border-color: themed("border_color");
- }
+ ::v-deep .van-hairline--bottom::after {
+ @include themify() {
+ border-color: themed("border_color");
}
+ }
}
.break-word {
- word-wrap: break-word;
- white-space: pre-wrap;
+ word-wrap: break-word;
+ white-space: pre-wrap;
}
.max-w-230 {
- max-width: 230px;
+ max-width: 230px;
}
.responser {
- position: relative;
+ position: relative;
- &::after {
- content: '';
- width: 0;
- height: 0;
- border-top: 10px solid transparent;
- border-bottom: 10px solid transparent;
+ &::after {
+ content: "";
+ width: 0;
+ height: 0;
+ border-top: 10px solid transparent;
+ border-bottom: 10px solid transparent;
- @include themify() {
- border-right: 2px solid themed("chat_bg");
- }
-
- position: absolute;
- left: -20px;
- top: 20px;
+ @include themify() {
+ border-right: 2px solid themed("chat_bg");
}
+
+ position: absolute;
+ left: -20px;
+ top: 20px;
+ }
}
.responser-two {
- position: relative;
+ position: relative;
- &::after {
- content: '';
- width: 0;
- height: 0;
- border-bottom: 10px solid transparent;
- border-top: 10px solid transparent;
+ &::after {
+ content: "";
+ width: 0;
+ height: 0;
+ border-bottom: 10px solid transparent;
+ border-top: 10px solid transparent;
- @include themify() {
- border-left: 20px solid themed("chat_bg");
- }
-
- position: absolute;
- right: -19px;
- top: 20px;
+ @include themify() {
+ border-left: 20px solid themed("chat_bg");
}
+
+ position: absolute;
+ right: -19px;
+ top: 20px;
+ }
}
.borderTop {
- @include themify() {
- border-top: 1px solid themed("border_color");
- }
+ @include themify() {
+ border-top: 1px solid themed("border_color");
+ }
}
.localKefu {
- overflow: auto;
- padding-bottom: 40px;
+ overflow: auto;
+ padding-bottom: 40px;
}
.van-nav-bar--fixed {
- position: relative !important;
+ position: relative !important;
}
.bottom {
- margin-bottom: constant(safe-area-inset-bottom);
- margin-bottom: env(safe-area-inset-bottom);
+ margin-bottom: constant(safe-area-inset-bottom);
+ margin-bottom: env(safe-area-inset-bottom);
}
</style>
--
Gitblit v1.9.3