lilishop-ui/im/src/components/chat/panel/TalkPanel.vue

1245 lines
32 KiB
Vue
Raw Normal View History

2022-12-28 10:08:51 +08:00
<template>
<div class="flex">
2022-12-28 18:31:26 +08:00
<el-container class="ov-hidden flex-10 full-height ">
2022-12-28 10:08:51 +08:00
<PanelHeader ref="panelHeader" :data="params" :online="isOnline" :keyboard="inputEvent"
@event="handleHeaderEvent" />
<!-- 主体信息 -->
<el-main class="main-box no-padding">
<div id="lumenChatPanel" class="talks-container lum-scrollbar" @scroll="talkPanelScroll($event)">
<!-- 数据加载状态栏 -->
<div class="loading-toolbar">
<span v-if="loadRecord.status == 0" class="color-blue">
<i class="el-icon-loading" /> 正在加载数据中...
</span>
<span v-if="loadRecord.status == 1" class="pointer color-blue" @click="loadChatRecords">
<i class="el-icon-bottom" /> 查看更多消息...
</span>
<span v-if="loadRecord.status == 2"> ... </span>
</div>
<!-- 消息主体 -->
<div v-for="(item, idx) in records" :key="idx">
<!-- 群消息 -->
<div v-if="item.messageType == 9" class="message-box">
<invite-message @cat="catFriendDetail" :invite="item.invite" />
</div>
<!-- 撤回消息 -->
<div v-else-if="item.is_revoke == 1" class="message-box">
<revoke-message :item="item" />
</div>
<div v-else-if="item.messageType == 0" class="message-box">
<system-text-message :content="item.content" />
</div>
<!-- 其它对话消息 -->
<div v-else class="message-box record-box" :class="{
2023-01-10 18:44:39 +08:00
'direction-rt': item.float == 'right',
'checkbox-border': multiSelect.isOpen === true,
}">
2022-12-28 10:08:51 +08:00
<aside v-show="multiSelect.isOpen" class="checkbox-column">
<i class="el-icon-success" :class="{ selected: verifyMultiSelect(item.id) }"
@click="triggerMultiSelect(item.id)" />
</aside>
<aside class="avatar-column">
<div class="avatar-box" v-if="item.float == 'right'">
<face :text="face" v-if="face"></face>
<face-null :text="name" v-else></face-null>
</div>
<div class="avatar-box" v-if="item.float == 'left'">
<face :text="toUser.face" v-if="toUser.face"></face>
<face-null :text="toUser.name" v-else></face-null>
</div>
</aside>
<main class="main-column">
<div class="talk-content">
<span class="nickname">
{{ item.float == "right" ? name : toUser.name }} |
{{ unixToDate(item.createTime, "MM月dd日 hh:mm") }}
</span>
<!-- 文本消息 -->
2023-01-10 18:44:39 +08:00
<div v-if="item.messageType == 'MESSAGE'" style="background-color: #d0e9ff;color: black;"
class="text-message" :class="{
left: item.float == 'left',
right: item.float == 'right',
}">
2022-12-28 10:08:51 +08:00
<div class="arrow"></div>
2023-01-13 10:53:39 +08:00
<pre v-if="!emojistwo.includes(item.text)" v-html="item.text" />
<pre v-if="emojistwo.includes(item.text)" v-html="textReplaceEmoji(item.text)" />
2022-12-28 10:08:51 +08:00
</div>
2023-01-10 18:44:39 +08:00
<div v-if="item.messageType == 'GOODS' && item.text != null" class="goodsStyle " :class="{
left: item.float == 'left',
right: item.float == 'right',
}">
2022-12-28 18:31:26 +08:00
<div class="base" @click="linkToGoods(item.text.goodsId, item.text.id)">
<div>
<img :src="item.text.thumbnail" class="image" />
</div>
2023-01-10 18:44:39 +08:00
<div>
<div class="goods_name">
<el-tooltip class="item" effect="dark" :content="item.text.goodsName" placement="top-start">
<a> {{ item.text.goodsName }} </a>
</el-tooltip>
</div>
<div class="price">
<span>{{ item.text.price }}</span>
2022-12-28 10:08:51 +08:00
</div>
2022-12-28 18:31:26 +08:00
</div>
2022-12-28 10:08:51 +08:00
</div>
</div>
2023-01-10 18:44:39 +08:00
<div v-if="item.messageType == 'ORDER' && item.text != null" class="oderStyle" :class="{
left: item.float == 'left',
right: item.float == 'right',
}">
<div class="oedersn">
<el-tooltip class="item" effect="dark" :content="item.text.sn" placement="top-start">
<a> 订单号:{{ item.text.sn }} </a>
</el-tooltip>
</div>
2022-12-29 18:20:06 +08:00
<div class="baseTwo">
<img :src="item.text.groupImages" style="height: 100px;width: 100px;margin-top: 10px;" />
<span class="orderGoodsName" @click="linkToOrders(item.text.sn)">{{ item.text.groupName }}</span>
<span class="orderGoodsTime">{{ item.text.paymentTime }}</span>
2023-01-10 18:44:39 +08:00
<span class="orderFlowPrice">
订单金额{{ item.text.flowPrice }}
</span>
<span class="order_status"
:style="{ 'color': item.text.orderStatus == 'CANCELLED' || item.text.orderStatus == 'UNPAID' || item.text.orderStatus == ' TAKE' ? '#5a606b' : '#f23030' }">{{
item.text.orderStatus == 'CANCELLED' ? '已取消' : item.text.orderStatus == 'UNPAID' ? '未付款' :
item.text.orderStatus ==
'PAID' ? '已付款' : item.text.orderStatus == 'UNDELIVERED' ? '待发货' : item.text.orderStatus ==
'DELIVERED'
? '已发货' : item.text.orderStatus == ' COMPLETED' ? '已完成' : item.text.orderStatus == ' TAKE' ?
'待校验' : ''
}}</span>
2022-12-29 18:20:06 +08:00
</div>
</div>
2022-12-28 10:08:51 +08:00
</div>
</main>
</div>
<!-- 消息时间 -->
<div v-show="compareTime(idx, item.createTime)" class="datetime no-select"
v-text="sendTime(unixToDate(item.createTime, 'yyyy-MM-dd hh:mm'))" />
</div>
</div>
<!-- 置底按钮 -->
<transition name="el-fade-in-linear">
<div v-show="tipsBoard" class="tips-board pointer" @click="talkPanelScrollBottom">
<!-- <SvgMentionDown class="svg" /> -->
<span>回到底部</span>
</div>
</transition>
<!-- 新消息气泡 -->
<div v-show="tipsBoard && unreadMessage.num" class="talk-bubble pointer no-select"
@click="talkPanelScrollBottom">
<i class="el-icon-chat-dot-round" />
<span>新消息({{ unreadMessage.num }})</span>
<span>
&nbsp;#{{ unreadMessage.nickname }}#
{{ unreadMessage.content }}
</span>
</div>
</el-main>
<!-- 页脚信息 -->
<el-footer class="footer-box" height="180">
<template v-if="multiSelect.isOpen === false">
<MeEditor @send="submitSendMessage" @keyboard-event="onKeyboardEvent" />
</template>
<template v-else>
<PanelToolbar v-model="multiSelect.items.length" @event="handleMultiMode" />
</template>
</el-footer>
<el-aside width="200px">
2022-12-28 18:31:26 +08:00
2022-12-28 10:08:51 +08:00
</el-aside>
2022-12-28 18:31:26 +08:00
2022-12-28 10:08:51 +08:00
</el-container>
<!-- 消息管理器 -->
<transition name="el-fade-in-linear">
<TalkSearchRecord v-if="findChatRecord" :params="{
2023-01-10 18:44:39 +08:00
talk_type: params.talk_type,
receiver_id: params.receiver_id,
title: params.nickname,
}" @close="findChatRecord = false" />
2022-12-28 10:08:51 +08:00
</transition>
<!-- 链接信息 -->
2023-02-01 15:03:40 +08:00
<OtherLink :toUser="toUser" :id="id" :goodsParams="goodsParams" class="flex-4" />
2022-12-28 10:08:51 +08:00
</div>
</template>
<script>
import { textReplaceLink } from "@/utils/functions";
2023-01-13 10:53:39 +08:00
import { textReplaceEmoji, emojistwo } from "@/utils/emojis";
2022-12-28 10:08:51 +08:00
import OtherLink from "@/components/chat/panel/OtherLink.vue";
import { mapState, mapGetters } from "vuex";
import TalkSearchRecord from "@/components/chat/TalkSearchRecord";
import MeEditor from "@/components/editor/MeEditor";
import PanelHeader from "./PanelHeader";
import PanelToolbar from "./PanelToolbar";
import SocketInstance from "@/im-server/socket-instance";
import { SvgMentionDown } from "@/core/icons";
import { formatTime, parseTime, copyTextToClipboard } from "@/utils/functions";
import {
ServeTalkRecords,
ServeForwardRecords,
ServeRemoveRecords,
ServeRevokeRecords,
} from "@/api/chat";
export default {
name: "TalkEditorPanel",
components: {
MeEditor,
OtherLink,
TalkSearchRecord,
SvgMentionDown,
PanelToolbar,
PanelHeader,
},
props: {
// 对话相关参数
params: {
type: Object,
default: function () {
return {
// 消息来源1好友私信 2:群聊)
talk_type: 0,
// 消息接收者ID好友ID或者群聊ID
receiver_id: 0,
nickname: "",
};
},
},
goodsParams: {
type: Object,
default: null,
},
// 用户是否在线
isOnline: {
type: Boolean,
default: false,
},
},
2022-12-28 18:31:26 +08:00
data () {
2022-12-28 10:08:51 +08:00
return {
// 记录加载相关参数
textReplaceEmoji,
2023-01-13 10:53:39 +08:00
emojistwo,
2022-12-28 10:08:51 +08:00
textReplaceLink,
loadRecord: {
status: 0,
minRecord: 0,
pageSize: 10,
pageNumber: 0,
},
// 多选相关操作
multiSelect: {
isOpen: false,
items: [],
mode: 0,
},
// 群组Box
group: {
panel: false,
notice: false,
},
// 键盘输入事件
keyboardEvent: {
isShow: false,
time: 0,
},
// 聊天记录管理器数据
findChatRecord: false,
// 置底按钮是否显示
tipsBoard: false,
};
},
computed: {
...mapGetters(["talkItems"]),
...mapState({
name: (state) => state.user.name,
face: (state) => state.user.face,
unreadMessage: (state) => state.talks.unreadMessage,
inputEvent: (state) => state.notify.inputEvent,
id: (state) => state.user.id,
records: (state) => state.dialogue.records,
index_name: (state) => state.dialogue.index_name,
toUser: (state) => state.user.toUser,
}),
},
watch: {
// 监听面板传递参数
2022-12-28 18:31:26 +08:00
params () {
2022-12-28 10:08:51 +08:00
this.loadRecord.minRecord = 0;
this.tipsBoard = false;
this.multiSelect = {
isOpen: false,
items: [],
mode: 0,
};
this.loadChatRecords();
2023-02-01 15:03:40 +08:00
2022-12-28 10:08:51 +08:00
},
},
2022-12-28 18:31:26 +08:00
mounted () {
2022-12-28 10:08:51 +08:00
this.loadChatRecords();
},
methods: {
parseTime,
sendTime: formatTime,
// 处理 Header 组件事件
2022-12-28 18:31:26 +08:00
handleHeaderEvent (event_name) {
2022-12-28 10:08:51 +08:00
switch (event_name) {
case "history":
this.findChatRecord = true;
break;
case "notice":
this.group.notice = true;
break;
case "setting":
this.group.panel = true;
break;
}
},
// linkTo(type,val){
// if(type === 'GOODS'){
// let routeUrl = this.$router.resolve({
// path: '/goodsDetail',
// query: { skuId:val.id, goodsId:val.goodsId }
// });
// window.open(routeUrl.href, '_blank');
// }
// },
// #TODO 冗余代码
2022-12-28 18:31:26 +08:00
formatDateToString (date) {
2022-12-28 10:08:51 +08:00
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
if (month < 10) month = "0" + month;
if (day < 10) day = "0" + day;
return year + "-" + month + "-" + day;
},
/**
* 将unix时间戳转换为指定格式
* @param unix 时间戳
* @param format 转换格式
* @returns {*|string}
*/
2022-12-28 18:31:26 +08:00
unixToDate (unix, format) {
2022-12-28 10:08:51 +08:00
if (!unix) return unix;
let _format = format || "yyyy-MM-dd hh:mm:ss";
const d = new Date(unix);
const o = {
"M+": d.getMonth() + 1,
"d+": d.getDate(),
"h+": d.getHours(),
"m+": d.getMinutes(),
"s+": d.getSeconds(),
"q+": Math.floor((d.getMonth() + 3) / 3),
S: d.getMilliseconds(),
};
if (/(y+)/.test(_format))
_format = _format.replace(
RegExp.$1,
(d.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (const k in o)
if (new RegExp("(" + k + ")").test(_format))
_format = _format.replace(
RegExp.$1,
RegExp.$1.length === 1
? o[k]
: ("00" + o[k]).substr(("" + o[k]).length)
);
return _format;
},
2022-12-28 18:31:26 +08:00
formateDateAndTimeToString (date) {
2022-12-28 10:08:51 +08:00
var hours = date.getHours();
var mins = date.getMinutes();
var secs = date.getSeconds();
var msecs = date.getMilliseconds();
if (hours < 10) hours = "0" + hours;
if (mins < 10) mins = "0" + mins;
if (secs < 10) secs = "0" + secs;
if (msecs < 10) secs = "0" + msecs;
return (
this.formatDateToString(date) + " " + hours + ":" + mins + ":" + secs
);
},
// #冗余代码结束
// 回车键发送消息回调事件
2022-12-28 18:31:26 +08:00
submitSendMessage (content) {
2022-12-28 10:08:51 +08:00
const record = {
operation_type: "MESSAGE",
to: this.params.receiver_id,
from: this.id,
message_type: "MESSAGE",
context: content,
talk_id: this.params.talkId,
};
2023-01-13 10:53:39 +08:00
// if (record.messageType == 'MESSAGE"') {
// record.text = this.textReplaceEmoji(record.content)
// }
2022-12-28 10:08:51 +08:00
SocketInstance.emit("event_talk", record);
this.$store.commit("UPDATE_TALK_ITEM", {
index_name: this.index_name,
draft_text: "",
});
/**
* 插入数据
*/
const insterChat = {
createTime: this.formateDateAndTimeToString(new Date()),
fromUser: this.id,
toUser: record.to,
isRead: false,
messageType: "MESSAGE",
text: content,
float: "right",
};
// console.log("插入对话记录",'')
// 插入对话记录
this.$store.commit("PUSH_DIALOGUE", insterChat);
// 获取聊天面板元素节点
let el = document.getElementById("lumenChatPanel");
// 判断的滚动条是否在底部
let isBottom =
Math.ceil(el.scrollTop) + el.clientHeight >= el.scrollHeight;
if (isBottom || record.to == this.id) {
this.$nextTick(() => {
el.scrollTop = el.scrollHeight;
});
} else {
this.$store.commit("SET_TLAK_UNREAD_MESSAGE", {
content: content,
nickname: record.name,
});
}
},
// 推送编辑事件消息
2022-12-28 18:31:26 +08:00
onKeyboardEvent (text) {
2022-12-28 10:08:51 +08:00
this.$store.commit("UPDATE_TALK_ITEM", {
index_name: this.index_name,
draft_text: text,
});
// 判断当前对话是否属于私聊信息
if (this.params.talk_type == 2 || !this.isOnline) return;
// 判断是否推送键盘输入事件消息
if (!this.$store.state.settings.keyboardEventNotify) {
return false;
}
let time = new Date().getTime();
// 判断在两秒内是否已推送事件
if (this.keyboardEvent.time != 0 && time - this.keyboardEvent.time < 2000)
return;
this.keyboardEvent.time = time;
// 调用父类Websocket组件发送消息
SocketInstance.emit("event_keyboard", {
sender_id: this.id,
receiver_id: this.params.receiver_id,
});
},
// 加载用户聊天详情信息
2022-12-28 18:31:26 +08:00
loadChatRecords () {
2022-12-28 10:08:51 +08:00
if (this.loadRecord.pageNumber === 0 || this.params.clickFlag) {
this.loadRecord.pageNumber = 1
this.params.clickFlag = false
} else {
this.loadRecord.pageNumber = this.loadRecord.pageNumber + 1
}
const user_id = this.id;
const data = {
2022-12-28 18:31:26 +08:00
pageNumber: this.loadRecord.pageNumber,
2022-12-28 10:08:51 +08:00
pageSize: this.loadChatRecords.pageSize,
talkId: this.params.talkId,
};
this.loadRecord.status = 0;
let el = document.getElementById('lumenChatPanel')
let scrollHeight = el.scrollHeight
ServeTalkRecords(data).then((res) => {
// 防止点击切换过快消息返回延迟,导致信息错误
// console.log("读取历史数据", res);
const records = res.result.map((item) => {
let key = new Date().getTime();
item.float = "center";
if (item.toUser > 0) {
item.float = item.fromUser == user_id ? "right" : "left";
}
2022-12-30 18:40:50 +08:00
if (item.messageType == 'GOODS') {
2022-12-28 10:08:51 +08:00
item.text = JSON.parse(item.text)
}
2023-01-13 10:53:39 +08:00
// if (item.messageType == 'MESSAGE"') {
// item.text = this.textReplaceEmoji(item.text)
// }
2022-12-30 18:40:50 +08:00
if (item.messageType == 'ORDER') {
2022-12-29 18:20:06 +08:00
item.text = JSON.parse(item.text)
}
2022-12-28 10:08:51 +08:00
return { ...item, [key]: key };
});
this.$store.commit("UNSHIFT_DIALOGUE", records);
records.length
? (this.loadRecord.status = 1)
: (this.loadRecord.status = 2);
this.$nextTick(() => {
2023-01-31 17:42:36 +08:00
// if (data.record_id == 0 || !data.record_id) {
if (data.record_id == 0 || data.pageNumber == 1) {
2022-12-28 10:08:51 +08:00
el.scrollTop = el.scrollHeight
} else {
el.scrollTop = el.scrollHeight - scrollHeight
}
})
});
},
// 多选处理方式
2022-12-28 18:31:26 +08:00
handleMultiMode (value) {
2022-12-28 10:08:51 +08:00
if (value == "close") {
this.closeMultiSelect();
return false;
}
if (this.multiSelect.items.length <= 1) {
return false;
}
if (value == "forward" || value == "merge_forward") {
this.multiSelect.mode = value == "forward" ? 1 : 2;
if (this.verifyMultiSelectType(3)) {
this.$notify({
title: "消息转发",
message: "会话记录不支持合并转发",
});
return false;
}
this.$contacts({
confirm: this.confirmSelectContacts,
});
} else if (value == "delete") {
this.multiSelect.mode = 3;
// 批量删除
let ids = this.multiSelect.items;
ServeRemoveRecords({
talk_type: this.params.talk_type,
receiver_id: this.params.receiver_id,
record_id: ids.join(","),
}).then((res) => {
if (res.code == 200) {
this.delRecords(ids).closeMultiSelect();
}
});
}
},
// 确认消息转发联系人事件
2022-12-28 18:31:26 +08:00
confirmSelectContacts (data) {
2022-12-28 10:08:51 +08:00
let user_ids = [];
let group_ids = [];
data.forEach((item) => {
if (item.type == 1) {
user_ids.push(item.id);
} else {
group_ids.push(item.id);
}
});
ServeForwardRecords({
forward_mode: this.multiSelect.mode,
talk_type: this.params.talk_type,
receiver_id: this.params.receiver_id,
records_ids: this.multiSelect.items,
receive_user_ids: user_ids,
receive_group_ids: group_ids,
}).then((res) => {
if (res.code == 200) {
this.closeMultiSelect();
this.$notify({
title: "消息转发",
message: "消息转发成功...",
type: "success",
});
}
});
},
// 处理消息时间是否显示
2022-12-28 18:31:26 +08:00
compareTime (index, datetime) {
2022-12-28 10:08:51 +08:00
if (datetime == undefined) {
return false;
}
if (typeof datetime == "number") {
datetime = this.unixToDate(datetime, "yyyy-MM-dd hh:mm");
}
if (this.records[index].is_revoke == 1) {
return false;
}
datetime = datetime.replace(/-/g, "/");
let time = Math.floor(Date.parse(datetime) / 1000);
let currTime = Math.floor(new Date().getTime() / 1000);
// 当前时间5分钟内时间不显示
if (currTime - time < 300) return false;
// 判断是否是最后一条消息,最后一条消息默认显示时间
if (index == this.records.length - 1) {
return true;
}
let nextDate = this.records[index + 1].createTime.replace(/-/g, "/");
return !(
parseTime(new Date(datetime), "{y}-{m}-{d} {h}:{i}") ==
parseTime(new Date(nextDate), "{y}-{m}-{d} {h}:{i}")
);
},
// 查看好友用户信息
2022-12-28 18:31:26 +08:00
catFriendDetail (value) {
2022-12-28 10:08:51 +08:00
this.$user(value);
},
// 撤回消息
2022-12-28 18:31:26 +08:00
revokeRecords (index, item) {
2022-12-28 10:08:51 +08:00
ServeRevokeRecords({
record_id: item.id,
}).then((res) => {
if (res.code == 200) {
this.$store.commit("UPDATE_DIALOGUE", { id: item.id, is_revoke: 1 });
}
});
},
// 删除消息
2022-12-28 18:31:26 +08:00
removeRecords (index, item) {
2022-12-28 10:08:51 +08:00
let receiver_id = item.receiver_id;
if (item.talk_type == 1 && item.user_id != this.id) {
receiver_id = item.user_id;
}
ServeRemoveRecords({
talk_type: item.talk_type,
receiver_id: receiver_id,
record_id: item.id.toString(),
}).then((res) => {
if (res.code == 200) {
this.$store.commit("DELETE_DIALOGUE", index);
}
});
},
// 从列表中删除记录
2022-12-28 18:31:26 +08:00
delRecords (arr) {
2022-12-28 10:08:51 +08:00
this.$store.commit("BATCH_DELETE_DIALOGUE", arr);
return this;
},
// 开启多选模式
2022-12-28 18:31:26 +08:00
openMultiSelect () {
2022-12-28 10:08:51 +08:00
this.multiSelect.isOpen = true;
},
// 关闭多选模式
2022-12-28 18:31:26 +08:00
closeMultiSelect () {
2022-12-28 10:08:51 +08:00
this.multiSelect.isOpen = false;
this.multiSelect.items = [];
},
// 判断记录是否选中
2022-12-28 18:31:26 +08:00
verifyMultiSelect (records_id) {
2022-12-28 10:08:51 +08:00
return this.multiSelect.items.indexOf(records_id) >= 0;
},
// 触发多选事件
2022-12-28 18:31:26 +08:00
triggerMultiSelect (records_id) {
2022-12-28 10:08:51 +08:00
let i = this.multiSelect.items.indexOf(records_id);
if (i >= 0) {
this.multiSelect.items.splice(i, 1);
} else {
if (this.multiSelect.items.length >= 30) {
this.$notify({
title: "温馨提示",
message: "批量操作最大支持30条数据...",
});
return false;
}
this.multiSelect.items.push(records_id);
}
},
// 验证是否存在选择的指定类型的消息
2022-12-28 18:31:26 +08:00
verifyMultiSelectType (type) {
2022-12-28 10:08:51 +08:00
return this.records.some((item) => {
return this.verifyMultiSelect(item.id) && item.messageType == type;
});
},
// 消息点击右键触发自定义菜单
2022-12-28 18:31:26 +08:00
onCopy (idx, item, event) {
2022-12-28 10:08:51 +08:00
let menus = [];
let content = "";
if (document.getElementById("copy_class_" + item.id)) {
content = document.getElementById("copy_class_" + item.id).innerText;
}
if (content) {
menus.push({
label: "复制",
icon: "el-icon-document-copy",
customClass: "cus-contextmenu-item",
onClick: () => {
copyTextToClipboard(content);
},
});
}
if (item.user_id == this.id) {
let time =
new Date().getTime() - Date.parse(item.createTime.replace(/-/g, "/"));
if (Math.floor(time / 1000 / 60) < 2) {
menus.push({
label: "撤回",
icon: "el-icon-s-flag",
customClass: "cus-contextmenu-item",
onClick: () => {
this.revokeRecords(idx, item);
},
});
}
}
menus.push({
label: "删除",
icon: "el-icon-delete",
customClass: "cus-contextmenu-item",
onClick: () => {
this.removeRecords(idx, item);
},
});
menus.push({
label: "引用",
icon: "el-icon-connection",
customClass: "cus-contextmenu-item",
onClick: () => { },
});
menus.push({
label: "多选",
icon: "el-icon-finished",
customClass: "cus-contextmenu-item",
onClick: () => {
this.openMultiSelect();
},
});
// 判断是否是图片消息
if (item.messageType == 2 && item.file.file_type == 1) {
menus.push({
label: "收藏",
icon: "el-icon-picture",
customClass: "cus-contextmenu-item",
onClick: () => {
this.$store.commit("SAVE_USER_EMOTICON", {
record_id: item.id,
});
},
});
}
this.$contextmenu({
items: menus,
event,
customClass: "cus-contextmenu",
zIndex: 3,
minWidth: 120,
});
this.closeMultiSelect();
event.preventDefault();
},
2022-12-28 18:31:26 +08:00
hideChatGroup () {
2022-12-28 10:08:51 +08:00
this.group.panel = false;
},
// 修改群聊免打扰状态
2022-12-28 18:31:26 +08:00
disturbChange (detail) {
2022-12-28 10:08:51 +08:00
this.$store.commit("UPDATE_TALK_ITEM", {
index_name: `2_${this.params.receiver_id}`,
is_disturb: parseInt(detail.status),
});
},
// 退出群聊回调事件
2022-12-28 18:31:26 +08:00
quitGroupSuccess () {
2022-12-28 10:08:51 +08:00
this.$emit("close-talk");
},
// 同步群信息
2022-12-28 18:31:26 +08:00
syncGroupInfo (groupInfo) {
2022-12-28 10:08:51 +08:00
this.$refs.panelHeader.setGroupNum(groupInfo.members_num);
},
// 对话面板滚动事件
2022-12-28 18:31:26 +08:00
talkPanelScroll (e) {
2022-12-28 10:08:51 +08:00
if (e.target.scrollTop == 0 && this.loadRecord.status == 1) {
this.loadChatRecords();
return;
}
const height = e.target.scrollTop + e.target.clientHeight + 5;
this.tipsBoard = height < e.target.scrollHeight;
if (this.tipsBoard == false && this.unreadMessage.num > 0) {
this.$store.commit("CLEAR_TLAK_UNREAD_MESSAGE");
}
},
// 聊天版本滚动到底部
2022-12-28 18:31:26 +08:00
talkPanelScrollBottom () {
2022-12-28 10:08:51 +08:00
let el = document.getElementById("lumenChatPanel");
el.scrollTop = el.scrollHeight;
},
},
};
</script>
<style lang="less" scoped>
2023-01-10 18:44:39 +08:00
.order_status {
height: 30px;
width: 60px;
background: #ffeded;
margin-right: 20px;
text-align: center;
line-height: 25px;
margin-left: 15px;
border-radius: 10px;
}
.oderStyle {
border: 1px solid #f2f2f2;
width: 330px;
border-radius: 4px;
.oedersn {
margin: 10px 0 10px 5px;
width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.goodsStyle {
border: 1px solid #f2f2f2;
width: 300px;
height: 120px;
display: flex;
border-radius: 4px;
.goods_name {
color: black;
width: 150px;
font-size: 15px;
color: #333333;
margin-top: 30px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.image {
height: 70px;
margin-top: 3px;
width: 70px;
background-size: cover;
margin: 20px;
}
.price {
color: #999;
margin-top: 20px;
}
.base {
display: flex;
}
}
2022-12-29 18:20:06 +08:00
.orderSn {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap
}
.orderGoodsName {
width: 200px;
overflow: hidden;
text-overflow: ellipsis;
2023-01-10 18:44:39 +08:00
// white-space: nowrap;
2022-12-29 18:20:06 +08:00
position: absolute;
margin-top: 10px;
margin-left: 10px;
}
.orderGoodsTime {
margin-left: 10px;
2023-01-10 18:44:39 +08:00
color: #999;
2022-12-29 18:20:06 +08:00
position: absolute;
2023-01-10 18:44:39 +08:00
margin-top: 70px;
}
.orderFlowPrice {
color: #999;
margin-bottom: 20px;
2022-12-29 18:20:06 +08:00
}
2022-12-28 10:08:51 +08:00
.main-box {
position: relative;
}
/* 面板页脚 */
.footer-box {
height: 160px !important;
padding: 0;
border-top: 1px solid #f5f5f5;
}
/* 侧边栏css */
.sidebar-box {
position: absolute;
width: 350px;
height: 100%;
top: 0px;
right: -350px;
z-index: 1;
background: white;
transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
-webkit-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;
&.show {
right: 0;
box-shadow: 0 0 14px #e2e1e1;
}
}
.tips-board {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
left: 0;
right: 0;
margin: 0 auto;
bottom: 20px;
height: 30px;
width: 100px;
border-radius: 20px;
font-size: 12px;
background-color: #fff;
box-shadow: 0 2.5px 10px 0 rgba(31, 35, 41, 0.1);
color: #1f2329;
span {
margin-left: 5px;
margin-top: -2px;
}
.svg {
width: 10px;
height: 10px;
color: black;
}
}
2022-12-28 18:31:26 +08:00
2022-12-29 18:20:06 +08:00
2023-01-10 18:44:39 +08:00
// .base {
// margin-top: 5px;
// height: 120px;
// display: flex;
2022-12-28 11:22:54 +08:00
2023-01-10 18:44:39 +08:00
// div {
// width: 100px;
// // overflow: hidden;
// // text-overflow: ellipsis;
// margin-top: 8px;
// // white-space: nowrap;
// }
2022-12-28 18:31:26 +08:00
2023-01-10 18:44:39 +08:00
// .image {
// height: 100px;
// margin-top: 3px;
// width: 100px
// }
2022-12-28 10:08:51 +08:00
2023-01-10 18:44:39 +08:00
// }
2022-12-28 18:31:26 +08:00
2022-12-28 10:08:51 +08:00
.talk-bubble {
position: absolute;
left: 0px;
bottom: 20px;
max-width: 300px;
height: 40px;
line-height: 40px;
border-radius: 0 20px 20px 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: white;
padding: 0 15px 0 30px;
font-size: 13px;
background: #409eff;
i {
font-size: 22px;
position: absolute;
left: 5px;
top: 9px;
}
}
.talks-container {
height: 100%;
width: 100%;
box-sizing: border-box;
padding: 10px 15px 30px;
overflow-y: auto;
.message-box {
width: 100%;
min-height: 30px;
margin-bottom: 5px;
}
.loading-toolbar {
height: 30px;
line-height: 30px;
margin: 5px 0;
text-align: center;
user-select: none;
font-size: 13px;
color: #cec4c4;
.color-blue {
color: #409eff;
}
}
.datetime {
height: 30px;
line-height: 30px;
color: #ccc9c9;
font-size: 12px;
text-align: center;
margin: 5px 0;
}
.record-box {
display: flex;
flex-direction: row;
transition: 0.5s ease;
.checkbox-column {
display: flex;
justify-content: center;
flex-basis: 40px;
flex-shrink: 0;
order: 1;
user-select: none;
padding-top: 25px;
i {
color: #ccc;
cursor: pointer;
font-size: 22px;
&.selected {
color: #409eff !important;
}
}
}
.avatar-column {
width: 40px;
flex-basis: 40px;
flex-shrink: 0;
display: flex;
align-items: center;
order: 2;
user-select: none;
padding-top: 22px;
flex-direction: column;
}
.main-column {
flex: 1 auto;
order: 3;
position: relative;
box-sizing: border-box;
padding: 5px;
overflow: hidden;
.talk-title {
display: flex;
align-items: center;
height: 15px;
margin-bottom: 2px;
font-size: 10px;
user-select: none;
color: #a7a0a0;
opacity: 0;
transition: 0.5s ease;
&.show {
opacity: 1 !important;
}
span {
transform: scale(0.9);
}
}
.talk-content {
display: flex;
flex-direction: column;
align-items: flex-start;
box-sizing: border-box;
width: 100%;
.nickname {
font-size: 12px;
color: #a7a0a0;
margin: -4px 0 4px -8px;
transform: scale(0.9);
}
}
&:hover {
.talk-title {
opacity: 1;
}
}
}
&.direction-rt {
.avatar-column {
order: 3;
}
.main-column {
order: 2;
.talk-title {
justify-content: flex-end;
}
.talk-content {
align-items: flex-end;
}
}
}
&.checkbox-border {
border: 1px dashed #c4c4ec;
&:hover {
border-color: #409eff;
}
}
}
}
@bg-left-color: #f5f5f5;
2023-01-10 18:44:39 +08:00
@bg-right-color: #ffffff;
2022-12-28 10:08:51 +08:00
.text-message {
position: relative;
min-width: 30px;
min-height: 30px;
border-radius: 5px;
padding: 5px;
.arrow {
position: absolute;
width: 0;
height: 0;
font-size: 0;
border: 5px solid;
top: 6px;
left: -10px;
}
&.max-width {
max-width: calc(100% - 50px);
}
&.left {
color: #3a3a3a;
background: @bg-left-color;
.arrow {
border-color: transparent @bg-left-color transparent transparent;
}
}
&.right {
color: #fff;
background: @bg-right-color;
.arrow {
right: -10px;
left: unset;
border-color: transparent transparent transparent @bg-right-color;
}
}
pre {
white-space: pre-wrap;
overflow: hidden;
word-break: break-word;
word-wrap: break-word;
font-size: 15px;
padding: 3px 10px;
font-family: "Microsoft YaHei";
line-height: 25px;
}
}
</style>