客服系统:1.滚动到列表下方分页请求历史用户列表拼接 完成 2.游客功能添加、删除列表离线游客 目前游客断开没有返回关闭信息 3.中英文翻译 处理中 4.客服页面添加回到底部功能 增加用户体验 完成
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<router-view class="page" />
|
<router-view class="page" />
|
||||||
<!-- <ChatWidget v-if="!$route.path.includes('/customerService')" /> -->
|
<ChatWidget v-if="!$route.path.includes('/customerService')" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script >
|
<script >
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="chat-widget">
|
<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
|
<div
|
||||||
class="chat-icon"
|
class="chat-icon"
|
||||||
@click="toggleChat"
|
@click="toggleChat"
|
||||||
:class="{ active: isChatOpen }"
|
:class="{ active: isChatOpen }"
|
||||||
aria-label="打开客服聊天"
|
:aria-label="$t('chat.openCustomerService') || '打开客服聊天'"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@keydown.enter="toggleChat"
|
@keydown.enter="toggleChat"
|
||||||
@keydown.space="toggleChat"
|
@keydown.space="toggleChat"
|
||||||
@@ -33,16 +38,16 @@
|
|||||||
class="chat-status connecting"
|
class="chat-status connecting"
|
||||||
>
|
>
|
||||||
<i class="el-icon-loading"></i>
|
<i class="el-icon-loading"></i>
|
||||||
<p>正在连接客服系统...</p>
|
<p>{{ $t("chat.connectToCustomerService") || "正在连接客服系统..." }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="connectionStatus === 'error'"
|
v-else-if="connectionStatus === 'error'"
|
||||||
class="chat-status error"
|
class="chat-status error"
|
||||||
>
|
>
|
||||||
<i class="el-icon-warning"></i>
|
<i class="el-icon-warning"></i>
|
||||||
<p>连接失败,请稍后重试</p>
|
<p>{{ $t("chat.connectionFailed") || "连接失败,请稍后重试" }}</p>
|
||||||
<button @click="connectWebSocket" class="retry-button">
|
<button @click="connectWebSocket" class="retry-button">
|
||||||
重试连接
|
{{ $t("chat.tryConnectingAgain") || "重试连接" }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -56,7 +61,7 @@
|
|||||||
>
|
>
|
||||||
<i class="el-icon-arrow-up"></i>
|
<i class="el-icon-arrow-up"></i>
|
||||||
<span>{{
|
<span>{{
|
||||||
isLoadingHistory ? "加载中..." : "加载更多历史消息"
|
isLoadingHistory ? $t("chat.loading") || "加载中..." : $t("chat.loadMore") || "加载更多历史消息"
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -103,7 +108,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="msg.imageUrl"
|
:src="msg.imageUrl"
|
||||||
@click="previewImage(msg.imageUrl)"
|
@click="previewImage(msg.imageUrl)"
|
||||||
alt="聊天图片"
|
:alt="$t('chat.picture') || '聊天图片'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -114,7 +119,7 @@
|
|||||||
v-if="msg.type === 'user'"
|
v-if="msg.type === 'user'"
|
||||||
class="message-read-status"
|
class="message-read-status"
|
||||||
>
|
>
|
||||||
{{ msg.isRead ? "已读" : "未读" }}
|
{{ msg.isRead ? $t("chat.read") || "已读" : $t("chat.unread") || "未读" }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -225,6 +230,11 @@ export default {
|
|||||||
maxReconnectAttempts: 5,
|
maxReconnectAttempts: 5,
|
||||||
reconnectInterval: 5000, // 5秒
|
reconnectInterval: 5000, // 5秒
|
||||||
isReconnecting: false,
|
isReconnecting: false,
|
||||||
|
lastActivityTime: Date.now(),
|
||||||
|
activityCheckInterval: null,
|
||||||
|
networkStatus: "online",
|
||||||
|
reconnectTimer: null,
|
||||||
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -247,6 +257,17 @@ export default {
|
|||||||
|
|
||||||
// 添加页面可见性变化监听
|
// 添加页面可见性变化监听
|
||||||
document.addEventListener("visibilitychange", this.handleVisibilityChange);
|
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: {
|
methods: {
|
||||||
// 初始化聊天系统
|
// 初始化聊天系统
|
||||||
@@ -305,7 +326,6 @@ export default {
|
|||||||
this.userType = 1;
|
this.userType = 1;
|
||||||
this.userEmail = email;
|
this.userEmail = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
console.error("解析用户信息失败:", parseError);
|
console.error("解析用户信息失败:", parseError);
|
||||||
// 解析失败时默认为游客
|
// 解析失败时默认为游客
|
||||||
@@ -332,7 +352,7 @@ export default {
|
|||||||
// 订阅个人消息频道
|
// 订阅个人消息频道
|
||||||
this.stompClient.subscribe(
|
this.stompClient.subscribe(
|
||||||
`/sub/queue/user/${this.userEmail}`,
|
`/sub/queue/user/${this.userEmail}`,
|
||||||
this.onMessageReceived,
|
this.onMessageReceived
|
||||||
// {
|
// {
|
||||||
// id: `chat_${this.userEmail}`,
|
// id: `chat_${this.userEmail}`,
|
||||||
// }
|
// }
|
||||||
@@ -341,7 +361,10 @@ export default {
|
|||||||
console.log("成功订阅消息频道:", `/sub/queue/user/${this.userEmail}`);
|
console.log("成功订阅消息频道:", `/sub/queue/user/${this.userEmail}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("订阅消息失败:", 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.subscribeToPersonalMessages();
|
||||||
|
|
||||||
// 显示连接成功提示
|
// 显示连接成功提示
|
||||||
this.$message.success("连接成功");
|
// this.$message.success("连接成功");
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
console.error("WebSocket Error:", error);
|
console.error("WebSocket Error:", error);
|
||||||
@@ -418,22 +441,31 @@ export default {
|
|||||||
},
|
},
|
||||||
// 添加新重连最多重连5次
|
// 添加新重连最多重连5次
|
||||||
handleDisconnect() {
|
handleDisconnect() {
|
||||||
|
if (this.isReconnecting) return;
|
||||||
|
|
||||||
this.isWebSocketConnected = false;
|
this.isWebSocketConnected = false;
|
||||||
this.connectionStatus = "error";
|
this.connectionStatus = "error";
|
||||||
this.isReconnecting = false;
|
this.isReconnecting = true;
|
||||||
|
|
||||||
// 如果重连次数未超过最大尝试次数,则尝试重连
|
// 清除之前的重连定时器
|
||||||
|
if (this.reconnectTimer) {
|
||||||
|
clearTimeout(this.reconnectTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用现有的重连逻辑
|
||||||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||||||
this.reconnectAttempts++;
|
this.reconnectAttempts++;
|
||||||
console.log(
|
console.log(
|
||||||
`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`
|
`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`
|
||||||
);
|
);
|
||||||
|
//连接断开,${this.reconnectInterval / 1000}秒后重试...
|
||||||
this.$message.warning(
|
this.$message.warning(
|
||||||
`连接断开,${this.reconnectInterval / 1000}秒后重试...`
|
`${this.$t("chat.break")},${this.reconnectInterval / 1000}${this.$t("chat.retry")}...`
|
||||||
);
|
);
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
|
|
||||||
|
this.reconnectTimer = setTimeout(() => {
|
||||||
if (!this.isWebSocketConnected) {
|
if (!this.isWebSocketConnected) {
|
||||||
this.connectWebSocket();
|
this.connectWebSocket();
|
||||||
}
|
}
|
||||||
@@ -441,10 +473,42 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
console.log("达到最大重连次数,停止重连");
|
console.log("达到最大重连次数,停止重连");
|
||||||
this.$message.error("连接失败,请刷新页面重试");
|
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() {
|
handleBeforeUnload() {
|
||||||
this.disconnectWebSocket();
|
this.disconnectWebSocket();
|
||||||
},
|
},
|
||||||
@@ -453,13 +517,13 @@ export default {
|
|||||||
sendMessage() {
|
sendMessage() {
|
||||||
if (!this.inputMessage.trim()) return;
|
if (!this.inputMessage.trim()) return;
|
||||||
|
|
||||||
// 检查 WebSocket 连接状态
|
// 检查 WebSocket 连接状态
|
||||||
if (!this.stompClient || !this.stompClient.connected) {
|
if (!this.stompClient || !this.stompClient.connected) {
|
||||||
console.log('发送消息时连接已断开,尝试重连...');
|
console.log("发送消息时连接已断开,尝试重连...");
|
||||||
this.$message.warning('连接已断开,正在重新连接...');
|
this.$message.warning("连接已断开,正在重新连接...");
|
||||||
this.handleDisconnect();
|
this.handleDisconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageText = this.inputMessage.trim();
|
const messageText = this.inputMessage.trim();
|
||||||
|
|
||||||
@@ -539,11 +603,22 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 处理页面可见性变化
|
// 处理页面可见性变化
|
||||||
|
// 处理页面可见性变化
|
||||||
handleVisibilityChange() {
|
handleVisibilityChange() {
|
||||||
// 当页面变为可见且聊天窗口已打开时,标记消息为已读
|
// 当页面变为可见且聊天窗口已打开时,标记消息为已读
|
||||||
if (!document.hidden && this.isChatOpen && this.roomId) {
|
if (!document.hidden && this.isChatOpen && this.roomId) {
|
||||||
this.markMessagesAsRead();
|
this.markMessagesAsRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加新的重连逻辑
|
||||||
|
if (!document.hidden) {
|
||||||
|
// 页面变为可见时,检查连接状态
|
||||||
|
if (!this.isWebSocketConnected) {
|
||||||
|
this.handleDisconnect();
|
||||||
|
}
|
||||||
|
// 更新最后活动时间
|
||||||
|
this.updateLastActivityTime();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 标记消息为已读
|
// 标记消息为已读
|
||||||
@@ -552,6 +627,7 @@ export default {
|
|||||||
const data = {
|
const data = {
|
||||||
roomId: this.roomId,
|
roomId: this.roomId,
|
||||||
userType: this.userType,
|
userType: this.userType,
|
||||||
|
email: this.userEmail,
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await getReadMessage(data);
|
const response = await getReadMessage(data);
|
||||||
@@ -576,149 +652,151 @@ export default {
|
|||||||
|
|
||||||
// 加载历史消息
|
// 加载历史消息
|
||||||
async loadHistoryMessages() {
|
async loadHistoryMessages() {
|
||||||
if (this.isLoadingHistory || !this.roomId) return;
|
if (this.isLoadingHistory || !this.roomId) return;
|
||||||
|
|
||||||
this.isLoadingHistory = true;
|
this.isLoadingHistory = true;
|
||||||
try {
|
try {
|
||||||
const response = await getHistory7({
|
const response = await getHistory7({
|
||||||
roomId: this.roomId,
|
roomId: this.roomId,
|
||||||
userType: this.userType,
|
userType: this.userType,
|
||||||
email: this.userEmail,
|
email: this.userEmail,
|
||||||
});
|
});
|
||||||
console.log("历史消息数据:", response);
|
console.log("历史消息数据:", response);
|
||||||
|
|
||||||
if (response?.code === 200 && Array.isArray(response.data)) {
|
if (response?.code === 200 && Array.isArray(response.data)) {
|
||||||
// 处理历史消息
|
// 处理历史消息
|
||||||
const historyMessages = response.data.map((msg) => ({
|
const historyMessages = response.data.map((msg) => ({
|
||||||
type: msg.isSelf === 1 ? "user" : "system",
|
type: msg.isSelf === 1 ? "user" : "system",
|
||||||
text: msg.content,
|
text: msg.content,
|
||||||
isImage: msg.type === 2,
|
isImage: msg.type === 2,
|
||||||
imageUrl: msg.type === 2 ? msg.content : null,
|
imageUrl: msg.type === 2 ? msg.content : null,
|
||||||
time: new Date(msg.createTime),
|
time: new Date(msg.createTime),
|
||||||
id: msg.id,
|
id: msg.id,
|
||||||
roomId: msg.roomId,
|
roomId: msg.roomId,
|
||||||
sender: msg.sendEmail,
|
sender: msg.sendEmail,
|
||||||
isHistory: true,
|
isHistory: true,
|
||||||
isRead: true,
|
isRead: true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// 按时间顺序排序
|
// 按时间顺序排序
|
||||||
this.messages = historyMessages.sort(
|
this.messages = historyMessages.sort(
|
||||||
(a, b) => new Date(a.time) - new Date(b.time)
|
(a, b) => new Date(a.time) - new Date(b.time)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 等待 DOM 更新和图片加载完成后再滚动
|
// 等待 DOM 更新和图片加载完成后再滚动
|
||||||
await this.$nextTick();
|
await this.$nextTick();
|
||||||
// 添加一个小延时确保所有内容都渲染完成
|
// 添加一个小延时确保所有内容都渲染完成
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.scrollToBottom(true); // 传入 true 表示强制滚动
|
this.scrollToBottom(true); // 传入 true 表示强制滚动
|
||||||
}, 100);
|
}, 100);
|
||||||
} else {
|
} else {
|
||||||
this.messages = [
|
this.messages = [
|
||||||
{
|
{
|
||||||
type: "system",
|
type: "system",
|
||||||
text: "暂无历史消息",
|
text: "暂无历史消息",
|
||||||
isSystemHint: true,
|
isSystemHint: true,
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("加载历史消息失败:", error);
|
console.error("加载历史消息失败:", error);
|
||||||
this.$message.error("加载历史消息失败");
|
this.$message.error("加载历史消息失败");
|
||||||
this.messages = [
|
this.messages = [
|
||||||
{
|
{
|
||||||
type: "system",
|
type: "system",
|
||||||
text: "加载历史消息失败,请重试",
|
text: "加载历史消息失败,请重试",
|
||||||
isSystemHint: true,
|
isSystemHint: true,
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
isError: true,
|
isError: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
} finally {
|
} finally {
|
||||||
this.isLoadingHistory = false;
|
this.isLoadingHistory = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 加载更多历史消息(超过7天的)
|
// 加载更多历史消息(超过7天的)
|
||||||
async loadMoreHistory() {
|
async loadMoreHistory() {
|
||||||
if (this.isLoadingHistory || !this.roomId) return;
|
if (this.isLoadingHistory || !this.roomId) return;
|
||||||
|
|
||||||
this.isLoadingHistory = true;
|
this.isLoadingHistory = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 获取当前消息列表中最旧消息的 ID
|
// 获取当前消息列表中最旧消息的 ID
|
||||||
const oldestMessage = this.messages.find(msg => !msg.isSystemHint && !msg.isLoading);
|
const oldestMessage = this.messages.find(
|
||||||
if (!oldestMessage || !oldestMessage.id) {
|
(msg) => !msg.isSystemHint && !msg.isLoading
|
||||||
console.warn('没有找到有效的消息ID');
|
);
|
||||||
this.hasMoreHistory = false;
|
if (!oldestMessage || !oldestMessage.id) {
|
||||||
return;
|
console.warn("没有找到有效的消息ID");
|
||||||
}
|
this.hasMoreHistory = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 显示加载中提示
|
// 显示加载中提示
|
||||||
const loadingMsg = {
|
const loadingMsg = {
|
||||||
type: "system",
|
type: "system",
|
||||||
text: "正在加载更多历史消息...",
|
text: "正在加载更多历史消息...",
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
};
|
};
|
||||||
this.messages.unshift(loadingMsg);
|
this.messages.unshift(loadingMsg);
|
||||||
|
|
||||||
// 获取更早的聊天记录,添加 id 参数
|
// 获取更早的聊天记录,添加 id 参数
|
||||||
const response = await getHistory7({
|
const response = await getHistory7({
|
||||||
roomId: this.roomId,
|
roomId: this.roomId,
|
||||||
userType: this.userType,
|
userType: this.userType,
|
||||||
email: this.userEmail,
|
email: this.userEmail,
|
||||||
id: oldestMessage.id // 添加最旧消息的 ID
|
id: oldestMessage.id, // 添加最旧消息的 ID
|
||||||
});
|
});
|
||||||
|
|
||||||
// 移除加载中提示
|
// 移除加载中提示
|
||||||
this.messages = this.messages.filter((msg) => !msg.isLoading);
|
this.messages = this.messages.filter((msg) => !msg.isLoading);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
response &&
|
response &&
|
||||||
response.code === 200 &&
|
response.code === 200 &&
|
||||||
response.data &&
|
response.data &&
|
||||||
response.data.length > 0
|
response.data.length > 0
|
||||||
) {
|
) {
|
||||||
// 处理并添加历史消息
|
// 处理并添加历史消息
|
||||||
const historyMessages = this.formatHistoryMessages(response.data);
|
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({
|
this.messages.unshift({
|
||||||
type: "system",
|
type: "system",
|
||||||
text: "没有更多历史消息了",
|
text: "加载更多历史消息失败",
|
||||||
isSystemHint: true,
|
isError: true,
|
||||||
time: new Date(),
|
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) {
|
formatHistoryMessages(messagesData) {
|
||||||
@@ -796,7 +874,7 @@ export default {
|
|||||||
|
|
||||||
// 构造消息对象
|
// 构造消息对象
|
||||||
const messageObj = {
|
const messageObj = {
|
||||||
type: data.sendUserType === this.userType ? "user" : "system", // 用户类型判断
|
type: data.sendEmail === this.userEmail ? "user" : "system",
|
||||||
text: data.content,
|
text: data.content,
|
||||||
isImage: data.type === 2,
|
isImage: data.type === 2,
|
||||||
imageUrl: data.type === 2 ? data.content : null,
|
imageUrl: data.type === 2 ? data.content : null,
|
||||||
@@ -884,47 +962,50 @@ export default {
|
|||||||
|
|
||||||
// 打开聊天框
|
// 打开聊天框
|
||||||
async toggleChat() {
|
async toggleChat() {
|
||||||
this.isChatOpen = !this.isChatOpen;
|
this.isChatOpen = !this.isChatOpen;
|
||||||
|
|
||||||
// 1. 判别身份
|
// 1. 判别身份
|
||||||
this.determineUserType();
|
|
||||||
|
|
||||||
// 2. 如果是客服,跳转到客服页面
|
|
||||||
if (this.userType === 2) {
|
|
||||||
const lang = this.$i18n.locale;
|
|
||||||
this.$router.push(`/${lang}/customerService`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isChatOpen) {
|
|
||||||
try {
|
|
||||||
// 确定用户类型
|
|
||||||
this.determineUserType();
|
this.determineUserType();
|
||||||
|
|
||||||
// 如果未连接或连接断开,则重新初始化 WebSocket
|
// 2. 如果是客服,跳转到客服页面
|
||||||
if (!this.isWebSocketConnected || this.connectionStatus === "disconnected") {
|
if (this.userType === 2) {
|
||||||
await this.connectWebSocket();
|
const lang = this.$i18n.locale;
|
||||||
|
this.$router.push(`/${lang}/customerService`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果消息列表为空,加载历史消息
|
if (this.isChatOpen) {
|
||||||
if (this.messages.length === 0) {
|
try {
|
||||||
await this.loadHistoryMessages();
|
// 确定用户类型
|
||||||
} else {
|
this.determineUserType();
|
||||||
// 如果已有消息,确保滚动到底部
|
|
||||||
await this.$nextTick();
|
|
||||||
setTimeout(() => {
|
|
||||||
this.scrollToBottom(true);
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标记消息为已读
|
// 如果未连接或连接断开,则重新初始化 WebSocket
|
||||||
await this.markMessagesAsRead();
|
if (
|
||||||
} catch (error) {
|
!this.isWebSocketConnected ||
|
||||||
console.error("初始化聊天失败:", error);
|
this.connectionStatus === "disconnected"
|
||||||
this.$message.error("初始化聊天失败,请重试");
|
) {
|
||||||
}
|
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() {
|
minimizeChat() {
|
||||||
this.isChatOpen = false;
|
this.isChatOpen = false;
|
||||||
@@ -996,20 +1077,20 @@ export default {
|
|||||||
},
|
},
|
||||||
//滚动到底部
|
//滚动到底部
|
||||||
scrollToBottom(force = false) {
|
scrollToBottom(force = false) {
|
||||||
if (!this.$refs.chatBody) return;
|
if (!this.$refs.chatBody) return;
|
||||||
|
|
||||||
const scrollOptions = {
|
const scrollOptions = {
|
||||||
top: this.$refs.chatBody.scrollHeight,
|
top: this.$refs.chatBody.scrollHeight,
|
||||||
behavior: force ? 'auto' : 'smooth' // 强制滚动时使用 'auto'
|
behavior: force ? "auto" : "smooth", // 强制滚动时使用 'auto'
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.$refs.chatBody.scrollTo(scrollOptions);
|
this.$refs.chatBody.scrollTo(scrollOptions);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 如果平滑滚动不支持,则直接设置
|
// 如果平滑滚动不支持,则直接设置
|
||||||
this.$refs.chatBody.scrollTop = this.$refs.chatBody.scrollHeight;
|
this.$refs.chatBody.scrollTop = this.$refs.chatBody.scrollHeight;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
formatTime(date) {
|
formatTime(date) {
|
||||||
if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
|
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) {
|
previewImage(imageUrl) {
|
||||||
this.previewImageUrl = imageUrl;
|
this.previewImageUrl = imageUrl;
|
||||||
@@ -1197,8 +1265,6 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
|
|
||||||
|
|
||||||
// 移除滚动监听
|
// 移除滚动监听
|
||||||
if (this.$refs.chatBody) {
|
if (this.$refs.chatBody) {
|
||||||
this.$refs.chatBody.removeEventListener("scroll", this.handleChatScroll);
|
this.$refs.chatBody.removeEventListener("scroll", this.handleChatScroll);
|
||||||
@@ -1209,12 +1275,29 @@ export default {
|
|||||||
this.handleVisibilityChange
|
this.handleVisibilityChange
|
||||||
);
|
);
|
||||||
// 确保在销毁时断开连接
|
// 确保在销毁时断开连接
|
||||||
if (this.stompClient) {
|
if (this.stompClient) {
|
||||||
this.stompClient.disconnect();
|
this.stompClient.disconnect();
|
||||||
this.stompClient = null;
|
this.stompClient = null;
|
||||||
}
|
}
|
||||||
// 断开 WebSocket 连接
|
// 断开 WebSocket 连接
|
||||||
this.disconnectWebSocket();
|
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>
|
</script>
|
||||||
@@ -1664,4 +1747,19 @@ export default {
|
|||||||
.chat-message-user .message-read-status {
|
.chat-message-user .message-read-status {
|
||||||
color: rgba(255, 255, 255, 0.7);
|
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>
|
</style>
|
||||||
@@ -10,6 +10,70 @@ export const ChatWidget_zh = {
|
|||||||
onlyImages:"只能上传图片文件!",
|
onlyImages:"只能上传图片文件!",
|
||||||
imageTooLarge:"图片大小不能超过5MB!",
|
imageTooLarge:"图片大小不能超过5MB!",
|
||||||
imageReceived:"已收到您的图片,我们会尽快处理您的问题。",
|
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!",
|
onlyImages:"Only image files can be uploaded!",
|
||||||
imageTooLarge:"The image size cannot exceed 5MB!",
|
imageTooLarge:"The image size cannot exceed 5MB!",
|
||||||
imageReceived:"We have received your image, and we will handle your question as soon as possible.",
|
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
@@ -21,12 +21,12 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<ul class="moveCurrencyBox" >
|
<ul class="moveCurrencyBox" >
|
||||||
<li @click="clickCurrency(item)" v-for="item in currencyList" :key="item.value">
|
<li @click="clickCurrency(item)" v-for="item in currencyList" :key="item.value">
|
||||||
<img :src="item.img" alt="coin" loading="lazy"/>
|
<img :src="item.img" alt="coin" loading="lazy"/>
|
||||||
<p>{{ item.label }}</p>
|
<p>{{ item.label }}</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
@@ -800,6 +800,7 @@ export default {
|
|||||||
.view{
|
.view{
|
||||||
color: #5721e4;
|
color: #5721e4;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,6 +827,7 @@ export default {
|
|||||||
// overflow: hidden;
|
// overflow: hidden;
|
||||||
padding: 5px 5px;
|
padding: 5px 5px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
// background: palegoldenrod;
|
// background: palegoldenrod;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@@ -841,7 +843,13 @@ export default {
|
|||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
.moveCurrencyBox li:hover {
|
||||||
|
box-shadow: 0px 0px 5px 2px #d2c3ea;
|
||||||
|
}
|
||||||
|
|
||||||
.currencySelect{
|
.currencySelect{
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1330,6 +1338,7 @@ export default {
|
|||||||
.view{
|
.view{
|
||||||
color: #5721e4;
|
color: #5721e4;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1359,6 +1368,7 @@ export default {
|
|||||||
padding: 5px 5px;
|
padding: 5px 5px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
// background: palegoldenrod;
|
// background: palegoldenrod;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 25px;
|
width: 25px;
|
||||||
@@ -1373,7 +1383,13 @@ export default {
|
|||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.moveCurrencyBox li:hover {
|
||||||
|
box-shadow: 0px 0px 5px 2px #d2c3ea;
|
||||||
|
}
|
||||||
.currencySelect{
|
.currencySelect{
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -3269,6 +3285,7 @@ export default {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
color: #6E3EDB;
|
color: #6E3EDB;
|
||||||
|
// background: palegoldenrod;
|
||||||
|
|
||||||
}
|
}
|
||||||
.view:hover{
|
.view:hover{
|
||||||
|
|||||||
1
mining-pool/test/css/app-42f9d7e6.e8e56d1b.css
Normal file
1
mining-pool/test/css/app-42f9d7e6.e8e56d1b.css
Normal file
File diff suppressed because one or more lines are too long
BIN
mining-pool/test/css/app-42f9d7e6.e8e56d1b.css.gz
Normal file
BIN
mining-pool/test/css/app-42f9d7e6.e8e56d1b.css.gz
Normal file
Binary file not shown.
1
mining-pool/test/css/app-72600b29.f02b800f.css
Normal file
1
mining-pool/test/css/app-72600b29.f02b800f.css
Normal file
File diff suppressed because one or more lines are too long
BIN
mining-pool/test/css/app-72600b29.f02b800f.css.gz
Normal file
BIN
mining-pool/test/css/app-72600b29.f02b800f.css.gz
Normal file
Binary file not shown.
1
mining-pool/test/css/app-8e0489d9.7553f600.css
Normal file
1
mining-pool/test/css/app-8e0489d9.7553f600.css
Normal file
File diff suppressed because one or more lines are too long
BIN
mining-pool/test/css/app-8e0489d9.7553f600.css.gz
Normal file
BIN
mining-pool/test/css/app-8e0489d9.7553f600.css.gz
Normal file
Binary file not shown.
@@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><meta name=google-site-verification content=pKAZogQ0NQ6L4j9-V58WJMjm7zYCFwkJXSJzWu9UDM8><meta name=robots content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"><meta name=googlebot content="index, follow"><meta name=googlebot-news content="index, follow"><meta name=bingbot content="index, follow"><link rel=alternate hreflang=zh href=https://m2pool.com/zh><link rel=alternate hreflang=en href=https://m2pool.com/en><link rel=alternate hreflang=x-default href=https://m2pool.com/en><meta property=og:title content="M2pool - Stable leading high-yield mining pool"><meta property=og:description content="M2Pool provides professional mining services, supporting multiple cryptocurrency mining"><meta property=og:url content=https://m2pool.com/en><meta property=og:site_name content=M2Pool><meta property=og:type content=website><meta property=og:image content=https://m2pool.com/logo.png><link rel=icon href=/favicon.ico><link rel=stylesheet href=//at.alicdn.com/t/c/font_4582735_7i8wfzc0art.css><title>M2pool - Stable leading high-yield mining pool</title><meta name=keywords content="M2Pool, cryptocurrency mining pool,Entropyx(enx),entropyx, bitcoin mining, DGB mining, mining pool service, 加密货币矿池, 比特币挖矿, DGB挖矿"><meta name=description content="M2Pool provides professional mining services, supporting multiple cryptocurrency mining, including nexa, grs, mona, dgb, rxd, enx"><meta name=format-detection content="telephone=no"><meta name=apple-mobile-web-app-capable content=yes><script defer src=/js/chunk-vendors-945ce2fe.648a91a9.js></script><script defer src=/js/chunk-vendors-aacc2dbb.d317c558.js></script><script defer src=/js/chunk-vendors-bc050c32.3f2f14d2.js></script><script defer src=/js/chunk-vendors-3003db77.d0b93d36.js></script><script defer src=/js/chunk-vendors-9d134daf.bb668c99.js></script><script defer src=/js/chunk-vendors-439af1fa.48a48f35.js></script><script defer src=/js/chunk-vendors-5c533fba.b9c00e08.js></script><script defer src=/js/chunk-vendors-96cecd74.a7d9b845.js></script><script defer src=/js/chunk-vendors-c2f7d60e.3710fdc2.js></script><script defer src=/js/chunk-vendors-89d5c698.2190b4ca.js></script><script defer src=/js/chunk-vendors-377fed06.159de137.js></script><script defer src=/js/chunk-vendors-5a805870.4cfc0ae8.js></script><script defer src=/js/chunk-vendors-cf2e0a28.c6e99da0.js></script><script defer src=/js/app-42f9d7e6.3d6812c5.js></script><script defer src=/js/app-5c551db8.068e1f5e.js></script><script defer src=/js/app-01dc9ae1.e746f05c.js></script><script defer src=/js/app-8e0489d9.e6feb21e.js></script><script defer src=/js/app-72600b29.ec821a84.js></script><script defer src=/js/app-f035d474.30e8939b.js></script><script defer src=/js/app-113c6c50.c73554a4.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/app-42f9d7e6.21e533d7.css rel=stylesheet><link href=/css/app-01dc9ae1.04da7d85.css rel=stylesheet><link href=/css/app-8e0489d9.105c6ba3.css rel=stylesheet><link href=/css/app-72600b29.f0fc86b8.css rel=stylesheet><link href=/css/app-f035d474.0e6b8898.css rel=stylesheet><link href=/css/app-113c6c50.729eb983.css rel=stylesheet></head><body><div id=app></div></body></html>
|
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><meta name=google-site-verification content=pKAZogQ0NQ6L4j9-V58WJMjm7zYCFwkJXSJzWu9UDM8><meta name=robots content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"><meta name=googlebot content="index, follow"><meta name=googlebot-news content="index, follow"><meta name=bingbot content="index, follow"><link rel=alternate hreflang=zh href=https://m2pool.com/zh><link rel=alternate hreflang=en href=https://m2pool.com/en><link rel=alternate hreflang=x-default href=https://m2pool.com/en><meta property=og:title content="M2pool - Stable leading high-yield mining pool"><meta property=og:description content="M2Pool provides professional mining services, supporting multiple cryptocurrency mining"><meta property=og:url content=https://m2pool.com/en><meta property=og:site_name content=M2Pool><meta property=og:type content=website><meta property=og:image content=https://m2pool.com/logo.png><link rel=icon href=/favicon.ico><link rel=stylesheet href=//at.alicdn.com/t/c/font_4582735_7i8wfzc0art.css><title>M2pool - Stable leading high-yield mining pool</title><meta name=keywords content="M2Pool, cryptocurrency mining pool,Entropyx(enx),entropyx, bitcoin mining, DGB mining, mining pool service, 加密货币矿池, 比特币挖矿, DGB挖矿"><meta name=description content="M2Pool provides professional mining services, supporting multiple cryptocurrency mining, including nexa, grs, mona, dgb, rxd, enx"><meta name=format-detection content="telephone=no"><meta name=apple-mobile-web-app-capable content=yes><script defer src=/js/chunk-vendors-945ce2fe.648a91a9.js></script><script defer src=/js/chunk-vendors-aacc2dbb.d317c558.js></script><script defer src=/js/chunk-vendors-bc050c32.3f2f14d2.js></script><script defer src=/js/chunk-vendors-3003db77.d0b93d36.js></script><script defer src=/js/chunk-vendors-9d134daf.bb668c99.js></script><script defer src=/js/chunk-vendors-439af1fa.48a48f35.js></script><script defer src=/js/chunk-vendors-5c533fba.b9c00e08.js></script><script defer src=/js/chunk-vendors-96cecd74.a7d9b845.js></script><script defer src=/js/chunk-vendors-c2f7d60e.3710fdc2.js></script><script defer src=/js/chunk-vendors-89d5c698.2190b4ca.js></script><script defer src=/js/chunk-vendors-377fed06.159de137.js></script><script defer src=/js/chunk-vendors-5a805870.4cfc0ae8.js></script><script defer src=/js/chunk-vendors-cf2e0a28.c6e99da0.js></script><script defer src=/js/app-42f9d7e6.12c435f1.js></script><script defer src=/js/app-5c551db8.69e18ab2.js></script><script defer src=/js/app-01dc9ae1.e746f05c.js></script><script defer src=/js/app-8e0489d9.5adbe93c.js></script><script defer src=/js/app-72600b29.e3c70da1.js></script><script defer src=/js/app-f035d474.30e8939b.js></script><script defer src=/js/app-113c6c50.c73554a4.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/app-42f9d7e6.e8e56d1b.css rel=stylesheet><link href=/css/app-01dc9ae1.04da7d85.css rel=stylesheet><link href=/css/app-8e0489d9.7553f600.css rel=stylesheet><link href=/css/app-72600b29.f02b800f.css rel=stylesheet><link href=/css/app-f035d474.0e6b8898.css rel=stylesheet><link href=/css/app-113c6c50.729eb983.css rel=stylesheet></head><body><div id=app></div></body></html>
|
||||||
1
mining-pool/test/js/app-42f9d7e6.12c435f1.js
Normal file
1
mining-pool/test/js/app-42f9d7e6.12c435f1.js
Normal file
File diff suppressed because one or more lines are too long
BIN
mining-pool/test/js/app-42f9d7e6.12c435f1.js.gz
Normal file
BIN
mining-pool/test/js/app-42f9d7e6.12c435f1.js.gz
Normal file
Binary file not shown.
1
mining-pool/test/js/app-5c551db8.69e18ab2.js
Normal file
1
mining-pool/test/js/app-5c551db8.69e18ab2.js
Normal file
File diff suppressed because one or more lines are too long
BIN
mining-pool/test/js/app-5c551db8.69e18ab2.js.gz
Normal file
BIN
mining-pool/test/js/app-5c551db8.69e18ab2.js.gz
Normal file
Binary file not shown.
1
mining-pool/test/js/app-72600b29.e3c70da1.js
Normal file
1
mining-pool/test/js/app-72600b29.e3c70da1.js
Normal file
File diff suppressed because one or more lines are too long
BIN
mining-pool/test/js/app-72600b29.e3c70da1.js.gz
Normal file
BIN
mining-pool/test/js/app-72600b29.e3c70da1.js.gz
Normal file
Binary file not shown.
1
mining-pool/test/js/app-8e0489d9.5adbe93c.js
Normal file
1
mining-pool/test/js/app-8e0489d9.5adbe93c.js
Normal file
File diff suppressed because one or more lines are too long
BIN
mining-pool/test/js/app-8e0489d9.5adbe93c.js.gz
Normal file
BIN
mining-pool/test/js/app-8e0489d9.5adbe93c.js.gz
Normal file
Binary file not shown.
@@ -1 +1 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://m2pool.com/en</loc><lastmod>2025-05-16T08:36:13.289Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-05-16T08:36:13.290Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>
|
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://m2pool.com/en</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-05-23T06:27:17.672Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>
|
||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://m2pool.com/zh</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-05-16T08:36:13.279Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>
|
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://m2pool.com/zh</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-05-23T06:27:17.662Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>
|
||||||
Binary file not shown.
Reference in New Issue
Block a user