From 089bf5d2378b3c4a61d795b2a92bede2c193b771 Mon Sep 17 00:00:00 2001
From: admin <344137771@qq.com>
Date: Tue, 06 Jan 2026 11:22:58 +0800
Subject: [PATCH] 1
---
src/components/chat2/index.vue | 548 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 548 insertions(+), 0 deletions(-)
diff --git a/src/components/chat2/index.vue b/src/components/chat2/index.vue
new file mode 100644
index 0000000..b347ccb
--- /dev/null
+++ b/src/components/chat2/index.vue
@@ -0,0 +1,548 @@
+<template>
+ <div class="chat" v-loading="loading">
+ <el-scrollbar style="height: 500px" ref="scroll">
+ <div
+ class="history"
+ @click="onMore"
+ :style="{ visibility: finished ? 'hidden' : 'visiable' }"
+ >
+ 历史记录
+ </div>
+ <!-- 对话框消息 -->
+ <ul>
+ <li v-for="(item, index) in chatList" :key="item.id">
+ <!-- v-if="showTime(index)" -->
+ <p class="date">
+ {{ item.createtime}}
+ </p>
+
+ <div
+ class="content-box"
+ :class="
+ item.send_receive === 'receive' ? 'justify-end' : 'justify-start'
+ "
+ >
+ <!-- 机器人消息 -->
+ <template v-if="item.send_receive === 'receive'">
+ <div
+ class="responser bg-grey px-50 py-35 font-30 rounded-lg font-26"
+ style="background: #1ebafc;color: #fff;"
+ >
+ <span style="font-size: 13px;margin-right: 10px;margin-top: 10px;">{{ item.delete_status == -1 ? '已撤回' :
+ item.is_read == 1 ? '已读' : '未读' }}</span>
+ <p
+ class="break-words"
+ style="max-width: 300px;background: #1ebafc;color: #fff;"
+ v-if="item.type === 'text'"
+ >
+ {{ item.content }}
+ </p>
+ <!-- <img v-else :src="item.content" class="w-200 h-200" @click="onPreview(item.content)"/> -->
+ <el-image
+ v-if="item.type === 'img' && !status[item.id] "
+ src="./load.png"
+ class="w-200 h-200"
+ @click="openLoad(`${item.id}`)"
+ ></el-image>
+ <el-image
+ v-if="item.type === 'img' && status[item.id] == 2 "
+ :src="item.content"
+ class="w-200 h-200"
+ @click="open(`${item.content}`)"
+ ></el-image>
+
+ <div class="loading" v-if="status[item.id]==1"></div>
+
+ </div>
+ <img src="./responser.png" class="avatar" style="margin-left: 20px;"/>
+ </template>
+ <!-- 用户消息 -->
+ <template v-else>
+ <img src="./avatar1.png" class="avatar" style=""/>
+ <div class="responser" >
+
+ <div>
+ <el-image
+ src="./load.png"
+ class="w-200 h-200"
+ :preview-src-list="[item.content]"
+ v-if="item.type === 'img' && !status[item.id] "
+ @click="openLoad(`${item.id}`)"
+ ></el-image>
+
+ <el-image
+ :src="`${item.content}`"
+ class="w-200 h-200"
+ :preview-src-list="[item.content]"
+ v-if="item.type === 'img' && status[item.id] == 2"
+ @click="open(`${item.content}`)"
+ ></el-image>
+ <div class="loading" v-if="status[item.id] == 1"></div>
+
+ <p class="break-words" v-if="item.type === 'text'" style="max-width: 300px">
+ {{ item.content }}
+ </p>
+ </div>
+
+ </div>
+ </template>
+
+ </div>
+ </li>
+ </ul>
+ </el-scrollbar>
+ <div class="input-box">
+ <img src="./photo.png" class="w-72 h-72" @click="test" />
+ <input
+ ref="upload"
+ type="file"
+ hidden
+ @change="onImageFileChanged"
+ accept="image/png, image/gif, image/jpeg, image/bmp, image/x-icon"
+ />
+ <input
+ ref="input"
+ type="text"
+ v-model="value"
+ placeholder="请输入您的消息..."
+ class="flex-1 mx-20 h-full border-none"
+ />
+ <!-- <el-input v-model="value" placeholder="请输入内容"></el-input> -->
+ <img v-if="this.$store.state.talks.sendStatus == 0" src="./send.png" class="w-72 h-72" @click="send('text', value)" />
+ <div v-if="this.$store.state.talks.sendStatus == 1" class="loading2"></div>
+ </div>
+ </div>
+</template>
+
+<script>
+import { _sendMsg, _getMsg, _uploadImage ,uploadImageChange} from "@/api/chat.api";
+import { openImage} from "@/common/image";
+export default {
+ name: "Chat",
+ data() {
+ return {
+ allChatList: [],
+ chatList: [],
+ value: "", //客服输入的消息
+ lastMsgId: "",
+ interval: null,
+ unread: 0,
+ loading: false,
+ finished: false, // 没有历史消息
+ msg:{},
+ order_no:0,
+ isShow:false,
+ lastId:"",
+ status:{}
+ };
+ },
+ created() {
+
+ // const model=navigator.userAgent;
+ // 判断是否是安卓手机,是则是true
+ // this.androidAttrs=model.indexOf('Android') > -1 || model.indexOf('Linux') >-1
+ // _getMsg().then(data => {
+ // console.log(data)
+ // })
+ },
+ beforeDestroy() {
+ this.clearInterval();
+ this.isShow = false;
+ },
+ methods: {
+ // onPreview(url) { // 预览
+ // ImagePreview([url])
+ // },
+ openLoad(id){
+ this.status[id] = 1;
+ let timer = setTimeout(() => {
+ clearTimeout(timer);
+ this.status[id] = 2;
+ },1500)
+ },
+ open(img) {
+ openImage(img);
+ },
+ close(){
+ this.isShow = false;
+ this.order_no = 0;
+ this.clearInterval();
+ this.chatList = [];
+ this.allChatList = [];
+ },
+ init(msg1){
+ this.isShow = true;
+ this.clearInterval();
+ this.chatList = [];
+ this.order_no = msg1.order_no || 0;
+ this.msg = msg1;
+ this.fetchList();
+ console.log("index = " + JSON.stringify(this.msg));
+ },
+ test() {
+ this.$refs["upload"].click();
+ console.log(111);
+ },
+ showTime(index) {
+ // 时间显示
+ if (index === 0) {
+ return true;
+ }
+ if (index === this.chatList.length - 1) {
+ return false;
+ }
+ if (
+ this.chatList[index].createtime.split(" ")[0] ===
+ this.chatList[index + 1].createtime.split(" ")[1]
+ ) {
+ return false;
+ }
+ },
+ onImageFileChanged(e) {
+ const file = e.target.files[0];
+ const isLt2M = file.size / 1024 / 1024 < 2;
+ if (!isLt2M) {
+ Toast.fail('上传头像图片大小不能超过 2MB!');
+ return false;
+ }
+ this.afterRead(file);
+ },
+ afterRead(file) {
+ // 文件上传
+ this.loading = true;
+ uploadImageChange(file,(url)=>{
+ if(!url){
+ this.loading = false;
+ return;
+ }
+ _sendMsg("img", url,this.msg.order_no||"",this.msg.party_id||"").then((data) => {
+ console.log(data.code)
+ console.log("已经发送消息了", data);
+ this.value = "";
+ this.scrollToBottom();
+ // document.getElementById('bottom').click()
+ this.fetchList();
+ this.loading = false;
+ });
+ })
+ // _uploadImage(file, (percent) => {
+ // console.log(percent);
+ // })
+ // .then((data) => {
+ // this.loading = false;
+ // this.send("img", data);
+ // })
+ // .catch(() => {
+ // this.loading = false;
+ // });
+ },
+ fetchList(message_id = "") {
+ // 获取消息列表
+ _getMsg(message_id,this.msg.order_no||"",this.msg.party_id||"").then((data1) => {
+ if(this.msg.order_no != this.order_no){
+ this.chatList = [];
+ }
+ let data = data1.data;
+ // console.log("获取消息列表 = " + JSON.stringify(data));
+ // this.lastMsgId
+ if (!this.lastMsgId) {
+ this.lastMsgId = data.length && data[data.length - 1]["id"];
+ }
+ //
+ if (data.length) {
+ if(!this.allChatList[this.msg.order_no]){
+ this.allChatList[this.msg.order_no] = [];
+ }
+ if (message_id) {
+ // 加载更多
+ this.lastMsgId = data[data.length - 1]["id"];
+ this.allChatList[this.msg.order_no] = [...data.reverse(), ...this.allChatList[this.msg.order_no]];
+ } else {
+ this.allChatList[this.msg.order_no] = [...this.allChatList[this.msg.order_no], ...data.reverse()];
+ let hash = {};
+ this.allChatList[this.msg.order_no] = this.allChatList[this.msg.order_no].reduce(function (preVal, curVal) {
+ hash[curVal.id]
+ ? " "
+ : (hash[curVal.id] = true && preVal.push(curVal));
+ return preVal;
+ }, []);
+ }
+ this.chatList = [...this.allChatList[this.msg.order_no]]
+ if (data.length < 10) {
+ this.finished = true;
+ }
+ } else {
+ this.chatList = [
+ // {
+ // id: "1",
+ // send_receive: "receive",
+ // content: "你好,欢迎来到我们的数字货币平台!",
+ // type: "text",
+ // },
+ ];
+ }
+ if (!message_id) {
+ this.clearInterval();
+ console.log("this.isShow = " + this.isShow);
+ if(this.isShow){
+ this.interval = setInterval(() => {
+ this.fetchList();
+ }, 1000);
+ }
+ }
+ if (!this.lastMsgId) {
+ this.scrollToBottom();
+ }
+ if(data.length > 0){
+ if(this.lastId!=data[data.length - 1]["id"]){
+ this.lastId = data[data.length - 1]["id"];
+ this.scrollToBottom();
+ if(data[data.length - 1]["send_receive"] != "receive"){
+ this.playAudioOfMute();
+ }
+ }
+ }
+
+ });
+ },
+ scrollToBottom() {
+ let timer = setTimeout(() => {
+ clearTimeout(timer);
+ this.$nextTick(() => {
+ this.$refs["scroll"].wrap.scrollTop = 20000000;
+ });
+ }, 500);
+ // this.$nextTick(() => {
+ // let scrollElem = this.$refs.scroll;
+ // scrollElem.scrollTo({ top: scrollElem.scrollHeight, behavior: 'smooth' });
+ // });
+ },
+ onMore() {
+ // 加载更多
+ this.fetchList(this.lastMsgId);
+ },
+ clearInterval() {
+ if (this.interval) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ fetchUnread() {
+ // 获取未读
+ _getUnreadMsg(this.msg.order_no||"",this.msg.party_id||"").then((data) => {
+ this.unread = data;
+ // console.log(data)
+ });
+ },
+ send(type = "text", content = "") {
+ // 发送消息, img 也当消息text
+ if (!content) {
+ const text = "请输入消息内容";
+ this.$message(text);
+ return;
+ }
+ if(this.$store.state.talks.sendStatus == 1){return;}
+ this.$store.commit('SET_SEND_STATUS', 1)
+ let timer = setTimeout(() => {
+ clearTimeout(timer);
+ this.$store.commit('SET_SEND_STATUS', 0);
+ },5000);
+ _sendMsg(type, content,this.msg.order_no||"",this.msg.party_id||"").then((data) => {
+ console.log("已经发送消息了", data);
+ this.$store.commit('SET_SEND_STATUS', 0)
+ this.value = "";
+ this.scrollToBottom();
+ // document.getElementById('bottom').click()
+ this.fetchList();
+ });
+ },
+ },
+ beforeDestroy() {
+ this.clearInterval();
+ this.isShow = false;
+ },
+};
+</script>
+
+<style scoped>
+/deep/ .el-scrollbar .el-scrollbar__wrap {
+ /* height: 620px; */
+ overflow-x: hidden;
+}
+
+.w-100 {
+ width: 200px;
+}
+.h-200 {
+ height: 200px;
+}
+.date {
+ text-align: center;
+ padding: 5px 0;
+ /* color: #fff; */
+ color:#000;
+}
+.justify-end {
+ justify-content: flex-end;
+}
+.chat {
+ width: 100%;
+ display: flex;
+ height: 100%;
+ flex-direction: column;
+}
+.history {
+ padding: 10px 0;
+ text-align: center;
+ width: 160px;
+ height: 40px;
+ line-height: 30px;
+ background: #f0f0f0;
+ margin: 0 auto;
+ cursor: pointer;
+ border-radius: 10px;
+ margin-top: 10px;
+}
+.history:hover {
+ background: #a8d3ec;
+ color: #fff;
+}
+ul {
+ /* display: flex; */
+ flex: 1;
+ /* overflow-y: scroll; */
+ /* flex-direction: column; */
+}
+ul li {
+ display: flex;
+ margin-bottom: 10px;
+ flex-direction: column;
+}
+ul li .content-box {
+ display: flex;
+ padding: 15px 10px;
+ width: 100%;
+ box-sizing: border-box;
+}
+ul li .content-box .avatar {
+ width: 40px;
+ height: 40px;
+ margin-right: 10px;
+}
+
+ul li .content-box .responser {
+ position: relative;
+ background: #f0f0f0;
+ padding: 10px 20px;
+ border-radius: 10px;
+}
+
+ul li .content-box.justify-end {
+ padding-right: 20px;
+}
+ul li .content-box.justify-end .responser::after {
+ content: "";
+ width: 0;
+ height: 0;
+ border-top: 10px solid transparent;
+ border-bottom: 10px solid transparent;
+ position: absolute;
+ top: 10px;
+ border-left: 20px solid #1ebafc;
+ right: -10px;
+ /* background-color: #1ebafc; */
+ color: #1ebafc;
+}
+
+ul li .content-box.justify-start .responser::after {
+ content: "";
+ width: 0;
+ height: 0;
+ border-top: 10px solid transparent;
+ border-bottom: 10px solid transparent;
+ border-right: 20px solid #f3f3f3;
+ position: absolute;
+ left: -10px;
+ top: 10px;
+}
+
+ul li .content-box .responser .break-words {
+ font-size: 16px;
+ color: #000;
+ word-break: break-all;
+}
+.input-box {
+ height: 50px;
+ border-top: 1px solid #f0f0f0;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ box-sizing: border-box;
+ padding: 0 10px;
+ position: relative;
+ z-index: 2;
+}
+.input-box input {
+ flex: 1;
+ height: 100%;
+ border: none;
+ outline: none;
+ padding-left: 5px;
+}
+.input-box img {
+ width: 35px;
+ height: 35px;
+}
+</style>
+
+<style>
+.loading {
+ position: relative;
+ width: 200px;
+ height: 200px;
+ border: 2px solid #000;
+ border-top-color: rgba(0, 0, 0, 0.2);
+ border-right-color: rgba(0, 0, 0, 0.2);
+ border-bottom-color: rgba(0, 0, 0, 0.2);
+ border-radius: 100%;
+
+ animation: circle infinite 0.75s linear;
+}
+
+@keyframes circle {
+ 0% {
+ transform: rotate(0);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+
+.loading2 {
+ position: relative;
+ left: 0%;
+ top: 0%;
+ width: 33px;
+ height: 33px;
+ border: 2px solid #000;
+ border-top-color: rgba(0, 0, 0, 0.2);
+ border-right-color: rgba(0, 0, 0, 0.2);
+ border-bottom-color: rgba(0, 0, 0, 0.2);
+ border-radius: 100%;
+
+ animation: circle infinite 0.75s linear;
+}
+
+@keyframes circle {
+ 0% {
+ transform: rotate(0);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+
+
+</style>
\ No newline at end of file
--
Gitblit v1.9.3