客服系统:1.滚动到列表下方分页请求历史用户列表拼接 完成 2.游客功能添加、删除列表离线游客 目前游客断开没有返回关闭信息 3.中英文翻译 处理中 4.客服页面添加回到底部功能 增加用户体验 完成

This commit is contained in:
2025-05-23 14:46:29 +08:00
parent d3ac95af75
commit 38fbb4e625
24 changed files with 1123 additions and 516 deletions

View File

@@ -1,7 +1,7 @@
<template>
<div id="app">
<router-view class="page" />
<!-- <ChatWidget v-if="!$route.path.includes('/customerService')" /> -->
<ChatWidget v-if="!$route.path.includes('/customerService')" />
</div>
</template>
<script >

View File

@@ -1,11 +1,16 @@
<template>
<div class="chat-widget">
<!-- 添加网络状态提示 -->
<div v-if="networkStatus === 'offline'" class="network-status">
<i class="el-icon-warning"></i>
<span>{{ $t("chat.networkError") || "网络连接已断开" }}</span>
</div>
<!-- 聊天图标 -->
<div
class="chat-icon"
@click="toggleChat"
:class="{ active: isChatOpen }"
aria-label="打开客服聊天"
:aria-label="$t('chat.openCustomerService') || '打开客服聊天'"
tabindex="0"
@keydown.enter="toggleChat"
@keydown.space="toggleChat"
@@ -33,16 +38,16 @@
class="chat-status connecting"
>
<i class="el-icon-loading"></i>
<p>正在连接客服系统...</p>
<p>{{ $t("chat.connectToCustomerService") || "正在连接客服系统..." }}</p>
</div>
<div
v-else-if="connectionStatus === 'error'"
class="chat-status error"
>
<i class="el-icon-warning"></i>
<p>连接失败请稍后重试</p>
<p>{{ $t("chat.connectionFailed") || "连接失败,请稍后重试" }}</p>
<button @click="connectWebSocket" class="retry-button">
重试连接
{{ $t("chat.tryConnectingAgain") || "重试连接" }}
</button>
</div>
@@ -56,7 +61,7 @@
>
<i class="el-icon-arrow-up"></i>
<span>{{
isLoadingHistory ? "加载中..." : "加载更多历史消息"
isLoadingHistory ? $t("chat.loading") || "加载中..." : $t("chat.loadMore") || "加载更多历史消息"
}}</span>
</div>
@@ -103,7 +108,7 @@
<img
:src="msg.imageUrl"
@click="previewImage(msg.imageUrl)"
alt="聊天图片"
:alt="$t('chat.picture') || '聊天图片'"
/>
</div>
@@ -114,7 +119,7 @@
v-if="msg.type === 'user'"
class="message-read-status"
>
{{ msg.isRead ? "已读" : "未读" }}
{{ msg.isRead ? $t("chat.read") || "已读" : $t("chat.unread") || "未读" }}
</span>
</div>
</div>
@@ -225,6 +230,11 @@ export default {
maxReconnectAttempts: 5,
reconnectInterval: 5000, // 5秒
isReconnecting: false,
lastActivityTime: Date.now(),
activityCheckInterval: null,
networkStatus: "online",
reconnectTimer: null,
};
},
@@ -247,6 +257,17 @@ export default {
// 添加页面可见性变化监听
document.addEventListener("visibilitychange", this.handleVisibilityChange);
// 添加网络状态变化监听
window.addEventListener("online", this.handleNetworkChange);
window.addEventListener("offline", this.handleNetworkChange);
// 添加用户活动检测
this.startActivityCheck();
// 添加用户活动监听
document.addEventListener("mousemove", this.updateLastActivityTime);
document.addEventListener("keydown", this.updateLastActivityTime);
document.addEventListener("click", this.updateLastActivityTime);
},
methods: {
// 初始化聊天系统
@@ -305,7 +326,6 @@ export default {
this.userType = 1;
this.userEmail = email;
}
} catch (parseError) {
console.error("解析用户信息失败:", parseError);
// 解析失败时默认为游客
@@ -332,7 +352,7 @@ export default {
// 订阅个人消息频道
this.stompClient.subscribe(
`/sub/queue/user/${this.userEmail}`,
this.onMessageReceived,
this.onMessageReceived
// {
// id: `chat_${this.userEmail}`,
// }
@@ -341,7 +361,10 @@ export default {
console.log("成功订阅消息频道:", `/sub/queue/user/${this.userEmail}`);
} catch (error) {
console.error("订阅消息失败:", error);
this.$message.error("消息订阅失败,可能无法接收新消息");
this.message({
message:this.$t("chat.subscriptionFailed")|| "消息订阅失败,可能无法接收新消息",
type:"error"
})
}
},
@@ -400,7 +423,7 @@ export default {
this.subscribeToPersonalMessages();
// 显示连接成功提示
this.$message.success("连接成功");
// this.$message.success("连接成功");
},
(error) => {
console.error("WebSocket Error:", error);
@@ -418,22 +441,31 @@ export default {
},
// 添加新重连最多重连5次
handleDisconnect() {
if (this.isReconnecting) return;
this.isWebSocketConnected = false;
this.connectionStatus = "error";
this.isReconnecting = false;
this.isReconnecting = true;
// 如果重连次数未超过最大尝试次数,则尝试重连
// 清除之前的重连定时器
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
}
// 使用现有的重连逻辑
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
console.log(
`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`
);
//连接断开,${this.reconnectInterval / 1000}秒后重试...
this.$message.warning(
`连接断开,${this.reconnectInterval / 1000}秒后重试...`
`${this.$t("chat.break")},${this.reconnectInterval / 1000}${this.$t("chat.retry")}...`
);
setTimeout(() => {
this.reconnectTimer = setTimeout(() => {
if (!this.isWebSocketConnected) {
this.connectWebSocket();
}
@@ -441,10 +473,42 @@ export default {
} else {
console.log("达到最大重连次数,停止重连");
this.$message.error("连接失败,请刷新页面重试");
this.isReconnecting = false;
}
},
// 处理网络状态变化
handleNetworkChange() {
this.networkStatus = navigator.onLine ? "online" : "offline";
// 新增:页面卸载时的处理
if (navigator.onLine) {
// 网络恢复时,尝试重连
if (!this.isWebSocketConnected) {
this.handleDisconnect();
}
} else {
// 网络断开时,显示提示
this.$message.warning("网络连接已断开,正在等待重连...");
}
},
// 开始活动检测
startActivityCheck() {
this.activityCheckInterval = setInterval(() => {
const now = Date.now();
const inactiveTime = now - this.lastActivityTime;
// 如果用户超过5分钟没有活动且连接断开则尝试重连
if (inactiveTime > 5 * 60 * 1000 && !this.isWebSocketConnected) {
this.handleDisconnect();
}
}, 60000); // 每分钟检查一次
},
// 更新最后活动时间
updateLastActivityTime() {
this.lastActivityTime = Date.now();
},
// 页面关闭时的处理
handleBeforeUnload() {
this.disconnectWebSocket();
},
@@ -453,13 +517,13 @@ export default {
sendMessage() {
if (!this.inputMessage.trim()) return;
// 检查 WebSocket 连接状态
if (!this.stompClient || !this.stompClient.connected) {
console.log('发送消息时连接已断开,尝试重连...');
this.$message.warning('连接已断开,正在重新连接...');
this.handleDisconnect();
return;
}
// 检查 WebSocket 连接状态
if (!this.stompClient || !this.stompClient.connected) {
console.log("发送消息时连接已断开,尝试重连...");
this.$message.warning("连接已断开,正在重新连接...");
this.handleDisconnect();
return;
}
const messageText = this.inputMessage.trim();
@@ -539,11 +603,22 @@ export default {
}
},
// 处理页面可见性变化
// 处理页面可见性变化
handleVisibilityChange() {
// 当页面变为可见且聊天窗口已打开时,标记消息为已读
if (!document.hidden && this.isChatOpen && this.roomId) {
this.markMessagesAsRead();
}
// 添加新的重连逻辑
if (!document.hidden) {
// 页面变为可见时,检查连接状态
if (!this.isWebSocketConnected) {
this.handleDisconnect();
}
// 更新最后活动时间
this.updateLastActivityTime();
}
},
// 标记消息为已读
@@ -552,6 +627,7 @@ export default {
const data = {
roomId: this.roomId,
userType: this.userType,
email: this.userEmail,
};
const response = await getReadMessage(data);
@@ -576,149 +652,151 @@ export default {
// 加载历史消息
async loadHistoryMessages() {
if (this.isLoadingHistory || !this.roomId) return;
if (this.isLoadingHistory || !this.roomId) return;
this.isLoadingHistory = true;
try {
const response = await getHistory7({
roomId: this.roomId,
userType: this.userType,
email: this.userEmail,
});
console.log("历史消息数据:", response);
this.isLoadingHistory = true;
try {
const response = await getHistory7({
roomId: this.roomId,
userType: this.userType,
email: this.userEmail,
});
console.log("历史消息数据:", response);
if (response?.code === 200 && Array.isArray(response.data)) {
// 处理历史消息
const historyMessages = response.data.map((msg) => ({
type: msg.isSelf === 1 ? "user" : "system",
text: msg.content,
isImage: msg.type === 2,
imageUrl: msg.type === 2 ? msg.content : null,
time: new Date(msg.createTime),
id: msg.id,
roomId: msg.roomId,
sender: msg.sendEmail,
isHistory: true,
isRead: true,
}));
if (response?.code === 200 && Array.isArray(response.data)) {
// 处理历史消息
const historyMessages = response.data.map((msg) => ({
type: msg.isSelf === 1 ? "user" : "system",
text: msg.content,
isImage: msg.type === 2,
imageUrl: msg.type === 2 ? msg.content : null,
time: new Date(msg.createTime),
id: msg.id,
roomId: msg.roomId,
sender: msg.sendEmail,
isHistory: true,
isRead: true,
}));
// 按时间顺序排序
this.messages = historyMessages.sort(
(a, b) => new Date(a.time) - new Date(b.time)
);
// 按时间顺序排序
this.messages = historyMessages.sort(
(a, b) => new Date(a.time) - new Date(b.time)
);
// 等待 DOM 更新和图片加载完成后再滚动
await this.$nextTick();
// 添加一个小延时确保所有内容都渲染完成
setTimeout(() => {
this.scrollToBottom(true); // 传入 true 表示强制滚动
}, 100);
} else {
this.messages = [
{
type: "system",
text: "暂无历史消息",
isSystemHint: true,
time: new Date(),
},
];
}
} catch (error) {
console.error("加载历史消息失败:", error);
this.$message.error("加载历史消息失败");
this.messages = [
{
type: "system",
text: "加载历史消息失败,请重试",
isSystemHint: true,
time: new Date(),
isError: true,
},
];
} finally {
this.isLoadingHistory = false;
}
},
// 等待 DOM 更新和图片加载完成后再滚动
await this.$nextTick();
// 添加一个小延时确保所有内容都渲染完成
setTimeout(() => {
this.scrollToBottom(true); // 传入 true 表示强制滚动
}, 100);
} else {
this.messages = [
{
type: "system",
text: "暂无历史消息",
isSystemHint: true,
time: new Date(),
},
];
}
} catch (error) {
console.error("加载历史消息失败:", error);
this.$message.error("加载历史消息失败");
this.messages = [
{
type: "system",
text: "加载历史消息失败,请重试",
isSystemHint: true,
time: new Date(),
isError: true,
},
];
} finally {
this.isLoadingHistory = false;
}
},
// 加载更多历史消息超过7天的
async loadMoreHistory() {
if (this.isLoadingHistory || !this.roomId) return;
if (this.isLoadingHistory || !this.roomId) return;
this.isLoadingHistory = true;
this.isLoadingHistory = true;
try {
// 获取当前消息列表中最旧消息的 ID
const oldestMessage = this.messages.find(msg => !msg.isSystemHint && !msg.isLoading);
if (!oldestMessage || !oldestMessage.id) {
console.warn('没有找到有效的消息ID');
this.hasMoreHistory = false;
return;
}
try {
// 获取当前消息列表中最旧消息的 ID
const oldestMessage = this.messages.find(
(msg) => !msg.isSystemHint && !msg.isLoading
);
if (!oldestMessage || !oldestMessage.id) {
console.warn("没有找到有效的消息ID");
this.hasMoreHistory = false;
return;
}
// 显示加载中提示
const loadingMsg = {
type: "system",
text: "正在加载更多历史消息...",
isLoading: true,
time: new Date(),
};
this.messages.unshift(loadingMsg);
// 显示加载中提示
const loadingMsg = {
type: "system",
text: "正在加载更多历史消息...",
isLoading: true,
time: new Date(),
};
this.messages.unshift(loadingMsg);
// 获取更早的聊天记录,添加 id 参数
const response = await getHistory7({
roomId: this.roomId,
userType: this.userType,
email: this.userEmail,
id: oldestMessage.id // 添加最旧消息的 ID
});
// 获取更早的聊天记录,添加 id 参数
const response = await getHistory7({
roomId: this.roomId,
userType: this.userType,
email: this.userEmail,
id: oldestMessage.id, // 添加最旧消息的 ID
});
// 移除加载中提示
this.messages = this.messages.filter((msg) => !msg.isLoading);
// 移除加载中提示
this.messages = this.messages.filter((msg) => !msg.isLoading);
if (
response &&
response.code === 200 &&
response.data &&
response.data.length > 0
) {
// 处理并添加历史消息
const historyMessages = this.formatHistoryMessages(response.data);
if (
response &&
response.code === 200 &&
response.data &&
response.data.length > 0
) {
// 处理并添加历史消息
const historyMessages = this.formatHistoryMessages(response.data);
// 将历史消息添加到消息列表的前面
this.messages = [...historyMessages, ...this.messages];
// 将历史消息添加到消息列表的前面
this.messages = [...historyMessages, ...this.messages];
// 如果没有数据返回,表示没有更多历史记录
this.hasMoreHistory = historyMessages.length > 0;
// 如果没有数据返回,表示没有更多历史记录
this.hasMoreHistory = historyMessages.length > 0;
if (historyMessages.length === 0) {
if (historyMessages.length === 0) {
this.messages.unshift({
type: "system",
text: "没有更多历史消息了",
isSystemHint: true,
time: new Date(),
});
}
} else {
this.hasMoreHistory = false;
this.messages.unshift({
type: "system",
text: "没有更多历史消息了",
isSystemHint: true,
time: new Date(),
});
}
} catch (error) {
console.error("加载更多历史消息失败:", error);
this.messages.unshift({
type: "system",
text: "没有更多历史消息",
isSystemHint: true,
text: "加载更多历史消息失败",
isError: true,
time: new Date(),
});
} finally {
this.isLoadingHistory = false;
}
} else {
this.hasMoreHistory = false;
this.messages.unshift({
type: "system",
text: "没有更多历史消息了",
isSystemHint: true,
time: new Date(),
});
}
} catch (error) {
console.error("加载更多历史消息失败:", error);
this.messages.unshift({
type: "system",
text: "加载更多历史消息失败",
isError: true,
time: new Date(),
});
} finally {
this.isLoadingHistory = false;
}
},
},
// 格式化历史消息数据
formatHistoryMessages(messagesData) {
@@ -796,7 +874,7 @@ export default {
// 构造消息对象
const messageObj = {
type: data.sendUserType === this.userType ? "user" : "system", // 用户类型判断
type: data.sendEmail === this.userEmail ? "user" : "system",
text: data.content,
isImage: data.type === 2,
imageUrl: data.type === 2 ? data.content : null,
@@ -884,47 +962,50 @@ export default {
// 打开聊天框
async toggleChat() {
this.isChatOpen = !this.isChatOpen;
this.isChatOpen = !this.isChatOpen;
// 1. 判别身份
this.determineUserType();
// 2. 如果是客服,跳转到客服页面
if (this.userType === 2) {
const lang = this.$i18n.locale;
this.$router.push(`/${lang}/customerService`);
return;
}
if (this.isChatOpen) {
try {
// 确定用户类型
// 1. 判别身份
this.determineUserType();
// 如果未连接或连接断开,则重新初始化 WebSocket
if (!this.isWebSocketConnected || this.connectionStatus === "disconnected") {
await this.connectWebSocket();
// 2. 如果是客服,跳转到客服页面
if (this.userType === 2) {
const lang = this.$i18n.locale;
this.$router.push(`/${lang}/customerService`);
return;
}
// 如果消息列表为空,加载历史消息
if (this.messages.length === 0) {
await this.loadHistoryMessages();
} else {
// 如果已有消息,确保滚动到底部
await this.$nextTick();
setTimeout(() => {
this.scrollToBottom(true);
}, 100);
}
if (this.isChatOpen) {
try {
// 确定用户类型
this.determineUserType();
// 标记消息为已读
await this.markMessagesAsRead();
} catch (error) {
console.error("初始化聊天失败:", error);
this.$message.error("初始化聊天失败,请重试");
}
}
},
// 如果未连接或连接断开,则重新初始化 WebSocket
if (
!this.isWebSocketConnected ||
this.connectionStatus === "disconnected"
) {
await this.connectWebSocket();
}
// 如果消息列表为空,加载历史消息
if (this.messages.length === 0) {
await this.loadHistoryMessages();
} else {
// 如果已有消息,确保滚动到底部
await this.$nextTick();
setTimeout(() => {
this.scrollToBottom(true);
}, 100);
}
// 标记消息为已读
await this.markMessagesAsRead();
} catch (error) {
console.error("初始化聊天失败:", error);
this.$message.error("初始化聊天失败,请重试");
}
}
},
minimizeChat() {
this.isChatOpen = false;
@@ -996,20 +1077,20 @@ export default {
},
//滚动到底部
scrollToBottom(force = false) {
if (!this.$refs.chatBody) return;
if (!this.$refs.chatBody) return;
const scrollOptions = {
top: this.$refs.chatBody.scrollHeight,
behavior: force ? 'auto' : 'smooth' // 强制滚动时使用 'auto'
};
const scrollOptions = {
top: this.$refs.chatBody.scrollHeight,
behavior: force ? "auto" : "smooth", // 强制滚动时使用 'auto'
};
try {
this.$refs.chatBody.scrollTo(scrollOptions);
} catch (error) {
// 如果平滑滚动不支持,则直接设置
this.$refs.chatBody.scrollTop = this.$refs.chatBody.scrollHeight;
}
},
try {
this.$refs.chatBody.scrollTo(scrollOptions);
} catch (error) {
// 如果平滑滚动不支持,则直接设置
this.$refs.chatBody.scrollTop = this.$refs.chatBody.scrollHeight;
}
},
formatTime(date) {
if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
@@ -1170,19 +1251,6 @@ export default {
}
},
// 确保 URL 是完整的方法
formatImageUrl(url) {
if (!url) return "";
// 如果已经是完整的 URL直接返回
if (url.startsWith("http://") || url.startsWith("https://")) {
return url;
}
// 否则添加基础路径
return process.env.VUE_APP_BASE_URL + url;
},
// 预览图片
previewImage(imageUrl) {
this.previewImageUrl = imageUrl;
@@ -1197,8 +1265,6 @@ export default {
},
beforeDestroy() {
// 移除滚动监听
if (this.$refs.chatBody) {
this.$refs.chatBody.removeEventListener("scroll", this.handleChatScroll);
@@ -1209,12 +1275,29 @@ export default {
this.handleVisibilityChange
);
// 确保在销毁时断开连接
if (this.stompClient) {
this.stompClient.disconnect();
this.stompClient = null;
}
if (this.stompClient) {
this.stompClient.disconnect();
this.stompClient = null;
}
// 断开 WebSocket 连接
this.disconnectWebSocket();
// 清除活动检测定时器
if (this.activityCheckInterval) {
clearInterval(this.activityCheckInterval);
}
// 清除重连定时器
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
}
// 移除新添加的事件监听
window.removeEventListener("online", this.handleNetworkChange);
window.removeEventListener("offline", this.handleNetworkChange);
document.removeEventListener("mousemove", this.updateLastActivityTime);
document.removeEventListener("keydown", this.updateLastActivityTime);
document.removeEventListener("click", this.updateLastActivityTime);
},
};
</script>
@@ -1664,4 +1747,19 @@ export default {
.chat-message-user .message-read-status {
color: rgba(255, 255, 255, 0.7);
}
.network-status {
position: fixed;
top: 20px;
right: 20px;
padding: 8px 16px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 8px;
z-index: 1000;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
background-color: #fef0f0;
color: #f56c6c;
}
</style>

View File

@@ -10,6 +10,70 @@ export const ChatWidget_zh = {
onlyImages:"只能上传图片文件!",
imageTooLarge:"图片大小不能超过5MB!",
imageReceived:"已收到您的图片,我们会尽快处理您的问题。",
networkError:"网络连接已断开,请刷新页面重试",
openCustomerService:"打开客服聊天",
connectToCustomerService:"正在连接客服系统...",
connectionFailed:"连接失败,请刷新页面重试",
tryConnectingAgain:"重试连接",
loading:"加载中...",
loadMore:"加载更多历史消息",
welcomeToUse:"欢迎使用在线客服,请问有什么可以帮您?",
picture:"聊天图片",
read:"已读",
unread:"未读",
subscriptionFailed:"消息订阅失败,可能无法接收新消息",
break:"连接断开",
retry:"秒后重试",
disconnectWaiting:"断线重连中...",
sendFailed:"发送消息失败,请重试",
noHistory:"暂无历史消息",
historicalFailure:"加载历史消息失败,请重试",
loadingHistory:"正在加载更多历史消息...",
noMoreHistory:"没有更多历史消息了",
Loaded:"已加载历史消息",
newMessage:"新消息",
pictureMessage:"图片消息",
initializationFailed:"初始化失败,请刷新页面重试",
beSorry:"抱歉,我暂时无法回答这个问题。请排队等待人工客服或提交工单。",
today:"今天",
yesterday:"昨天",
canOnlyUploadImages:"只能上传图片文件!",
imageSizeExceeded:"图片大小不能超过5MB!",
uploading:"正在上传图片...",
pictureFailed:"发送图片失败,请重试",
readImage:"读取图片失败,请重试",
processingFailed:"图片处理失败,请重试",
Disconnected:"连接已断开",
reconnecting:"正在重连...",
contactList:"联系列表",
search:"搜索最近联系人",
tourist:"游客",
important:"重要",
markAsImportant:"标记为重要",
cancelImportant:"已取消重要标记",
markingFailed:"标记操作失败,请重试",
select:"请选择联系人",
notSelected:"您尚未选择联系人",
None:"暂无消息记录",
sendPicture:"发送图片",
inputMessage:"请输入消息按Enter键发送按Ctrl+Enter键换行",
bottom:"回到底部",
Preview:"预览图片",
chatRoom:"聊天室",
CLOSED:"已关闭",
picture2:"图片",
Unnamed:"未命名聊天室",
noNewsAtTheMoment:"暂无消息",
contactFailed:"加载更多联系人失败",
listException:"获取聊天室列表异常",
my:"我",
unknownSender:"未知发送者",
recordFailed:"加载聊天记录失败",
messageException:"加载消息异常",
chooseFirst:"请先选择联系人",
chatDisconnected:"聊天连接已断开,请刷新页面重试",
pictureSuccessful:"图片已发送",
},
@@ -28,5 +92,73 @@ export const ChatWidget_en = {
onlyImages:"Only image files can be uploaded!",
imageTooLarge:"The image size cannot exceed 5MB!",
imageReceived:"We have received your image, and we will handle your question as soon as possible.",
}
networkError: "Network disconnected, please refresh page",
openCustomerService: "Open customer service chat",
connectToCustomerService: "Connecting to customer service...",
connectionFailed: "Connection failed, please refresh page",
tryConnectingAgain: "Retry connection",
loading: "Loading...",
loadMore: "Load more history",
welcomeToUse: "Welcome to online service, how can I help you?",
picture: "Chat image",
read: "Read",
unread: "Unread",
subscriptionFailed: "Message subscription failed",
break: "Connection lost",
retry: "Retry in seconds",
disconnectWaiting: "Reconnecting...",
sendFailed: "Send failed, please retry",
noHistory: "No history",
historicalFailure: "Failed to load history",
loadingHistory: "Loading more history...",
noMoreHistory: "No more history",
Loaded: "History loaded",
newMessage: "New message",
pictureMessage: "Image message",
initializationFailed: "Initialization failed, please refresh",
beSorry: "Sorry, I cannot answer this. Please wait for agent or submit ticket",
today: "Today",
yesterday: "Yesterday",
canOnlyUploadImages: "Only image files allowed",
imageSizeExceeded: "Image size exceeds 5MB",
uploading: "Uploading image...",
pictureFailed: "Failed to send image",
readImage: "Failed to read image",
processingFailed: "Image processing failed",
Disconnected: "Disconnected",
reconnecting: "Reconnecting...",
contactList: "Contact list",
search: "Search contacts",
tourist: "Guest",
important: "Important",
markAsImportant: "Mark as important",
cancelImportant: "Unmarked as important",
markingFailed: "Marking failed",
select: "Select contact",
notSelected: "No contact selected",
None: "No messages",
sendPicture: "Send image",
inputMessage: "Type message, Enter to send, Ctrl+Enter for new line",
bottom: "Back to bottom",
Preview: "Preview image",
chatRoom: "Chat room",
CLOSED: "Closed",
picture2: "Image",
Unnamed: "Unnamed chat",
noNewsAtTheMoment: "No messages",
contactFailed: "Failed to load contacts",
listException: "Failed to get chat list",
my: "Me",
unknownSender: "Unknown sender",
recordFailed: "Failed to load chat records",
messageException: "Failed to load messages",
chooseFirst: "Please select contact first",
chatDisconnected: "Chat disconnected, please refresh",
pictureSuccessful: "Image sent",
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -21,12 +21,12 @@
</span>
</template>
<ul class="moveCurrencyBox" >
<li @click="clickCurrency(item)" v-for="item in currencyList" :key="item.value">
<img :src="item.img" alt="coin" loading="lazy"/>
<p>{{ item.label }}</p>
</li>
</ul>
<ul class="moveCurrencyBox" >
<li @click="clickCurrency(item)" v-for="item in currencyList" :key="item.value">
<img :src="item.img" alt="coin" loading="lazy"/>
<p>{{ item.label }}</p>
</li>
</ul>
</el-submenu>
@@ -800,6 +800,7 @@ export default {
.view{
color: #5721e4;
margin-left: 5px;
cursor: pointer;
}
}
@@ -826,6 +827,7 @@ export default {
// overflow: hidden;
padding: 5px 5px;
box-sizing: border-box;
cursor: pointer;
// background: palegoldenrod;
img {
@@ -841,7 +843,13 @@ export default {
text-transform: capitalize;
}
}
}
.moveCurrencyBox li:hover {
box-shadow: 0px 0px 5px 2px #d2c3ea;
}
.currencySelect{
display: flex;
align-items: center;
@@ -1330,6 +1338,7 @@ export default {
.view{
color: #5721e4;
margin-left: 5px;
cursor: pointer;
}
}
@@ -1359,6 +1368,7 @@ export default {
padding: 5px 5px;
box-sizing: border-box;
// background: palegoldenrod;
cursor: pointer;
img {
width: 25px;
@@ -1373,7 +1383,13 @@ export default {
text-transform: capitalize;
}
}
}
.moveCurrencyBox li:hover {
box-shadow: 0px 0px 5px 2px #d2c3ea;
}
.currencySelect{
display: flex;
align-items: center;
@@ -3269,6 +3285,7 @@ export default {
cursor: pointer;
margin-left: 8px;
color: #6E3EDB;
// background: palegoldenrod;
}
.view:hover{