客服系统:1.滚动到列表下方分页请求历史用户列表拼接 完成 2.游客功能添加、删除列表离线游客 目前游客断开没有返回关闭信息 3.中英文翻译 处理中 4.客服页面添加回到底部功能 增加用户体验 完成
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user