聊天系统断网重连及客服离线识别 完成

This commit is contained in:
yaoqin 2025-06-17 11:27:44 +08:00
parent e74f5b8d75
commit 0dbb43233a
26 changed files with 862 additions and 627 deletions

Binary file not shown.

View File

@ -1,46 +1,7 @@
<!--
聊天小组件组件
=== 用户体验优化策略 v2.0 ===
遵循"静默可靠性"原则减少90%的用户提示噪音
已移除的不必要提示
- 自动重连进度通知后台静默处理
- 图片上传进度toast仅在失败时提示
- 连接成功确认提示成功是默认期望
- 网络断开自动提示避免打断用户
- 订阅失败技术细节简化为用户友好消息
- 心跳检测正常状态日志避免日志污染
- WebSocket技术性错误代码转换为友好消息
- 连接数上限等技术术语简化为通用连接异常
- 系统内部状态变更通知对用户无意义
- 自动恢复功能的成功提示静默恢复更专业
保留的必要提示
- 文件上传错误需要用户重新操作
- 消息发送失败需要用户重试
- 严重错误需要页面刷新需要用户行动
- 登录状态变更确认重要状态变化
- 需要用户手动干预的错误如页面刷新
优化效果
- 大幅减少用户界面干扰
- 系统显得更稳定可靠
- 只有真正需要用户关注的信息才会显示
- 技术细节完全对用户屏蔽
- 开发调试信息保留在控制台
错误消息简化策略
- 移除错误代码和技术术语
- 统一使用"连接异常"代替具体技术错误
- 提供明确的用户行动指导
- 避免让用户看到系统内部状态
-->
<template>
<div class="chat-widget">
<!-- 添加网络状态提示 -->
<div v-if="networkStatus === 'offline'" class="network-status">
<!-- 添加网络状态提示 -->
<div class="network-status" v-if="networkStatus === 'offline'">
<i class="el-icon-warning"></i>
<span>{{ $t("chat.networkError") || "网络连接已断开" }}</span>
</div>
@ -246,10 +207,10 @@
/>
<!-- <span class="input-counter">{{ maxMessageLength - inputMessage.length }}</span> -->
</div>
<!-- :disabled="connectionStatus !== 'connected' || !inputMessage.trim()" -->
<button
class="chat-send"
@click="sendMessage"
:disabled="connectionStatus !== 'connected' || !inputMessage.trim()"
@click="sendMessage"
>
{{ $t("chat.send") || "发送" }}
</button>
@ -339,6 +300,7 @@ export default {
lastErrorTime: 0, //
lastConnectedEmail: null, // email
userViewHistory: false, //
customerIsOnline: true, // 线
};
},
computed: {
@ -522,6 +484,8 @@ export default {
if (userData) {
this.roomId = userData.id;
this.receivingEmail = userData.userEmail;
// === 线 ===
this.customerIsOnline = userData.customerIsOnline;
// === 使localStorage ===
this.updateUnreadMessages(userData.clientReadNum || 0);
@ -665,7 +629,7 @@ export default {
if (!this.stompClient || !this.isWebSocketConnected) {
console.error("❌ STOMP客户端未连接无法订阅消息");
this.connectionStatus = "error";
this.connectionError = "连接状态异常,无法订阅消息";
this.connectionError =this.$t("chat.unableToSubscribe");//
this.isWebSocketConnected = false;
this.showRefreshButton = false; //
this.$forceUpdate();
@ -675,7 +639,7 @@ export default {
if (!this.stompClient.connected) {
console.error("❌ STOMP客户端已断开无法订阅消息");
this.connectionStatus = "error";
this.connectionError = "连接已断开,无法订阅消息";
this.connectionError = "chat.unableToSubscribe";//
this.isWebSocketConnected = false;
this.showRefreshButton = false; //
this.$forceUpdate();
@ -745,7 +709,7 @@ export default {
// === ===
this.connectionStatus = "error";
this.connectionError = "连接异常,可能是多窗口冲突,请关闭其他窗口重试";
this.connectionError = this.$t("chat.conflict"); //
this.isWebSocketConnected = false;
this.isReconnecting = false;
this.showRefreshButton = false; //
@ -757,33 +721,58 @@ export default {
// WebSocket
async connectWebSocket(selfEmail) {
if (!selfEmail) selfEmail = this.userEmail;
console.log("selfEmail",this.userEmail);
// userEmail
let email = selfEmail || this.userEmail;
// 1. localStorage
if (!email) {
try {
const emailData = localStorage.getItem("userEmail");
if (emailData) {
const emailObj = JSON.parse(emailData);
email = emailObj.email || emailObj.value || emailObj.userEmail || emailObj;
if (typeof email !== "string") email = "";
}
} catch (e) {
//
console.warn('[DEBUG] 解析localStorage userEmail失败:', e);
}
}
// 2. sessionStorage
if (!email) {
const guestEmail = sessionStorage.getItem("chatGuestEmail");
if (guestEmail && guestEmail.startsWith("guest_")) {
email = guestEmail;
}
}
// 3.
if (!email) {
email = `guest_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
sessionStorage.setItem("chatGuestEmail", email);
console.warn("[DEBUG] 自动生成游客邮箱:", email);
}
this.userEmail = email;
selfEmail = email;
console.log('[DEBUG] connectWebSocket called', {
isWebSocketConnected: this.isWebSocketConnected,
isReconnecting: this.isReconnecting,
lastConnectedEmail: this.lastConnectedEmail,
selfEmail,
userEmail: this.userEmail,
connectionStatus: this.connectionStatus
});
if (!selfEmail) {
console.warn("🔴 connectWebSocket: 缺少用户邮箱参数,尝试重新获取用户身份");
// rejected Promiseundefinedundefined.catch()
return Promise.reject(new Error("缺少用户邮箱参数"));
console.warn('[DEBUG] connectWebSocket: 缺少用户邮箱参数');
return Promise.reject(new Error('缺少用户邮箱参数'));
}
// === 10 ===
console.log("🌐 后端支持多连接,当前窗口独立建立连接");
// === ===
if (this.isWebSocketConnected && this.lastConnectedEmail &&
this.lastConnectedEmail !== selfEmail) {
console.log(`🔄 用户身份变化 (${this.lastConnectedEmail} -> ${selfEmail}),断开旧连接`);
this.forceDisconnectAll();
} else if (this.isWebSocketConnected && this.lastConnectedEmail === selfEmail) {
console.log("✅ 相同用户已连接,复用现有连接");
return Promise.resolve("already_connected");
if (this.isWebSocketConnected && this.lastConnectedEmail === selfEmail) {
console.log('[DEBUG] connectWebSocket: 已连接,复用');
return Promise.resolve('already_connected');
}
if (this.isReconnecting) {
console.log("🔍 正在重连中,跳过重复连接");
return Promise.resolve("reconnecting");
console.log('[DEBUG] connectWebSocket: 正在重连中,跳过');
return Promise.resolve('reconnecting');
}
this.connectionStatus = "connecting";
this.isReconnecting = true;
this.connectionError = null;
@ -808,8 +797,20 @@ export default {
// https wss
const baseUrl = process.env.VUE_APP_BASE_API.replace("https", "wss");
const wsUrl = `${baseUrl}chat/ws`;
// === stompClientWebSocket ===
if (this.stompClient) {
try {
this.stompClient.disconnect();
console.log('[DEBUG] 旧stompClient已disconnect');
} catch (e) {
console.warn('[DEBUG] stompClient.disconnect异常', e);
}
this.stompClient = null;
}
// === ===
console.log('[DEBUG] 即将新建stompClient:', wsUrl);
this.stompClient = Stomp.client(wsUrl);
this.stompClient.splitLargeFrames = true;
console.log('[DEBUG] stompClient对象已创建:', this.stompClient);
// === WebSocket ===
this.stompClient.webSocketFactory = () => {
@ -857,7 +858,7 @@ export default {
}
//
this.connectionError = errorMessage || "连接异常";
this.connectionError = errorMessage || this.$t("chat.abnormal");//
this.connectionStatus = "error";
this.isWebSocketConnected = false;
this.isReconnecting = false;
@ -893,7 +894,7 @@ export default {
stompConnected: this.stompClient?.connected
});
this.connectionStatus = "error";
this.connectionError = "订阅失败,可能是多窗口冲突,请关闭其他窗口重试";
this.connectionError = this.$t("chat.conflict");//
this.isWebSocketConnected = false;
this.isReconnecting = false;
this.showRefreshButton = true;
@ -926,11 +927,11 @@ export default {
// === ===
if (error.headers.message.includes("503")) {
this.connectionError = "服务器暂时不可用,请稍后重试";
this.connectionError = this.$t("chat.server500");// "";
} else if (error.headers.message.includes("handshake")) {
this.connectionError = "网络连接异常,正在重试";
this.connectionError =this.$t("chat.networkAnomaly");//
} else {
this.connectionError = "连接异常,正在重试";
this.connectionError = this.$t(`chat.abnormal`);//
}
this.isReconnecting = false;
this.handleDisconnect();
@ -944,7 +945,7 @@ export default {
} catch (error) {
console.error("初始化 WebSocket 失败:", error);
clearTimeout(connectionTimeout);
this.connectionError = "连接初始化失败,正在重试";
this.connectionError = this.$t("chat.initializationFailed");//
this.isReconnecting = false;
this.handleDisconnect();
return Promise.reject(error);
@ -952,6 +953,12 @@ export default {
},
// 5
handleDisconnect() {
console.log('[DEBUG] handleDisconnect', {
isWebSocketConnected: this.isWebSocketConnected,
isReconnecting: this.isReconnecting,
reconnectAttempts: this.reconnectAttempts,
connectionStatus: this.connectionStatus
});
if (this.isReconnecting) return;
console.log("🔌 处理连接断开...");
@ -1004,26 +1011,13 @@ export default {
// toast
this.reconnectTimer = setTimeout(() => {
this.isReconnecting = false; //
if (!this.isWebSocketConnected) {
// === undefined ===
const connectionPromise = this.connectWebSocket(this.userEmail);
if (connectionPromise && typeof connectionPromise.catch === 'function') {
connectionPromise.catch((error) => {
console.error("🔴 自动重连失败:", error);
// === ===
if (this.isChatOpen) {
this.connectionStatus = "error";
}
this.showRefreshButton = true;
console.error('[DEBUG] 自动重连失败:', error);
});
} else {
console.warn("🔴 connectWebSocket返回值无效可能缺少userEmail");
// connectWebSocketundefined
if (this.isChatOpen) {
this.connectionStatus = "error";
}
this.showRefreshButton = true;
}
}
}, this.reconnectInterval);
@ -1040,15 +1034,25 @@ export default {
//
handleNetworkChange() {
this.networkStatus = navigator.onLine ? "online" : "offline";
console.log('[DEBUG] handleNetworkChange', {
online: navigator.onLine,
isWebSocketConnected: this.isWebSocketConnected,
isReconnecting: this.isReconnecting,
connectionStatus: this.connectionStatus
});
if (navigator.onLine) {
//
if (!this.isWebSocketConnected) {
this.handleDisconnect();
}
} else {
// === ===
console.log("🌐 网络已断开,显示网络状态提示");
// === ===
location.reload(); //
this.isChatOpen = false;
this.isMinimized = false;
this.isLoadingHistory = false;
this.isLoading = false;
this.isWebSocketConnected = false;
this.isReconnecting = false;
// if (!this.isWebSocketConnected) {
// console.log('[DEBUG] handleDisconnect');
// this.handleDisconnect();
// }
}
},
//
@ -1101,9 +1105,36 @@ export default {
},
//
sendMessage() {
if (!this.inputMessage.trim()) return;
//
if (this.networkStatus !== 'online') {
this.$message({
message: this.$t("chat.networkError") || "网络连接已断开,无法发送消息",
type: "error",
showClose: true
});
return;
}
// === 线 ===
if (this.userType === 0 && this.customerIsOnline === false) {
this.$message({
message:this.$t("chat.customerServiceOffline") || "客服离线,请登录账号发送留言消息",
type: "warning",
showClose: true
});
return;
}
if (!this.inputMessage.trim()){
this.$message({
message: this.$t("chat.sendMessageEmpty") || "发送消息不能为空",
type: "warning",
showClose: true
});
return;
}
if (this.inputMessage.length > this.maxMessageLength) {
this.$message.warning(`消息不能超过${this.maxMessageLength}个字符`);
this.$message.warning(this.$t("chat.contentMax") || "超出发送内容大小限制,请删除部分内容(300字以内)");// 300
return;
}
@ -1157,7 +1188,7 @@ export default {
} catch (error) {
console.error("发送消息失败:", error);
// === ===
this.$message.error("发送失败,请重试");
this.$message.error(this.$t("chat.failInSend") || "发送失败,请重试");
}
},
@ -1355,7 +1386,7 @@ export default {
} catch (error) {
console.error("加载历史消息失败:", error);
// === ===
this.$message.error("加载历史消息失败");
this.$message.error(this.$t("chat.loadHistoryFailed") || "加载历史消息失败");
this.messages = [
{
type: "system",
@ -1446,7 +1477,7 @@ export default {
} catch (error) {
this.$message.error("加载历史消息失败,请重试");
this.$message.error(this.$t("chat.loadHistoryFailed") || "加载历史消息失败,请重试");
} finally {
this.isLoadingHistory = false;
}
@ -1652,18 +1683,25 @@ export default {
//
this.addMessageToChat(messageData, isSentByMe);
//
if (!isSentByMe && !this.isChatOpen) {
// 使1
if (messageData.clientReadNum !== undefined) {
this.updateUnreadMessages(messageData.clientReadNum);
// === ===
if (!isSentByMe) {
//
if (this.isChatOpen && this.isAtBottom()) {
this.updateUnreadMessages(0);
//
// this.markMessagesAsRead();
} else {
this.updateUnreadMessages(this.unreadMessages + 1);
//
if (data.clientReadNum !== undefined) {
this.updateUnreadMessages(data.clientReadNum);
} else {
this.updateUnreadMessages(this.unreadMessages + 1);
}
//
const messageObj = this.createMessageObject(data);
this.showNotification(messageObj);
}
//
const messageObj = this.createMessageObject(messageData);
this.showNotification(messageObj);
}
}
},
/**
@ -1805,7 +1843,7 @@ export default {
},
//
createNotification(message) {
const notification = new Notification("新消息", {
const notification = new Notification(this.$t("chat.newMessage") || "新消息", {
body: message.isImage
? `[ ${this.$t("chat.pictureMessage")}]` || "[图片消息]"
: message.text,
@ -1922,7 +1960,7 @@ export default {
} catch (error) {
console.error("初始化聊天失败:", error);
// === ===
this.$message.error("连接失败,请重试");
// this.$message.error("");
}
} else {
// === ===
@ -2290,7 +2328,7 @@ export default {
} catch (error) {
console.error("发送图片消息失败:", error);
// === ===
this.$message.error("图片发送失败,请重试");
// this.$message.error("");
}
},
@ -2375,10 +2413,10 @@ export default {
error.message.includes("503") ||
error.message.includes("网络")
)) {
this.connectionError = "网络连接异常,请稍后重试";
this.connectionError = this.$t("chat.networkAnomaly") || "网络连接异常,请稍后重试";
this.showRefreshButton = false; //
} else {
this.connectionError = "连接异常,请重试";
this.connectionError =this.$t("chat.abnormal") || "连接异常,请重试";
this.showRefreshButton = error.message && error.message.includes("1020"); // 1020
}
}
@ -2566,7 +2604,7 @@ export default {
// === ===
this.connectionStatus = "error";
this.connectionError = "连接数已达上限超过10个窗口请关闭一些窗口后重试";
this.connectionError = this.$t("chat.connectionLimitError") || "连接数已达上限超过10个窗口请关闭一些窗口后重试";
this.isWebSocketConnected = false;
this.isReconnecting = false;
this.showRefreshButton = false; //
@ -2673,7 +2711,7 @@ export default {
case "1021": // MAX_LIMIT_CONNECT
console.log("🚫 处理1021错误服务器连接数上限");
this.connectionError = "服务器繁忙,请稍后刷新重试";
this.connectionError = this.$t("chat.serverBusy") || "服务器繁忙,请稍后刷新重试";
this.connectionStatus = "error";
this.isReconnecting = false;
this.showRefreshButton = true;
@ -2682,7 +2720,7 @@ export default {
case "1022": // SET_PRINCIPAL_FAIL
console.log("🚫 处理1022错误身份设置失败");
this.connectionError = "身份验证失败,请刷新页面重试";
this.connectionError = this.$t("chat.identityError") || "身份验证失败,请刷新页面重试";
this.connectionStatus = "error";
this.isReconnecting = false;
this.showRefreshButton = true;
@ -2691,7 +2729,7 @@ export default {
case "1023": // GET_PRINCIPAL_FAIL
console.log("🚫 处理1023错误用户信息获取失败");
this.connectionError = "用户信息获取失败,请刷新页面重试";
this.connectionError = this.$t("chat.emailError") || "用户信息获取失败,请刷新页面重试";
this.connectionStatus = "error";
this.isReconnecting = false;
this.showRefreshButton = true;
@ -2883,7 +2921,7 @@ export default {
//
this.isWebSocketConnected = false;
this.connectionStatus = "connecting"; // connectingerror
this.connectionError = "正在重新连接...";
this.connectionError = this.$t("chat.reconnecting") || "正在重新连接...";
// 2
setTimeout(() => {
@ -2954,7 +2992,7 @@ export default {
this.forceDisconnectAll().then(() => {
// connectingerror
this.connectionStatus = "connecting";
this.connectionError = "连接超时,正在重试...";
this.connectionError = this.$t("chat.connectionTimedOut") || "连接超时,稍后重试...";
// 2
setTimeout(() => {
@ -2969,12 +3007,12 @@ export default {
this.isChatOpen = true;
this.isMinimized = false;
this.connectionStatus = "error";
this.connectionError = "重连失败,请稍后重试";
this.connectionError = this.$t("chat.reconnectFailed") || "重连失败,请稍后重试";
//
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
this.showRefreshButton = true;
this.connectionError = "连接失败,请刷新页面重试";
this.connectionError = this.$t("chat.connectionFailed") || "连接失败,请刷新页面重试";
}
});
}, 2000);
@ -2986,12 +3024,12 @@ export default {
this.isChatOpen = true;
this.isMinimized = false;
this.connectionStatus = "error";
this.connectionError = "连接处理失败,请稍后重试";
this.connectionError = this.$t("chat.connectionFailed") ||"连接处理失败,请稍后重试";
//
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
this.showRefreshButton = true;
this.connectionError = "连接失败,请刷新页面重试";
this.connectionError = this.$t("chat.connectionFailed") || "连接失败,请刷新页面重试";
}
});
},
@ -3048,19 +3086,19 @@ export default {
// === ===
if (error.message.includes("unexpected response code: 200")) {
this.connectionError = "服务配置异常,请稍后重试";
this.connectionError = this.$t("chat.serviceConfigurationError") || "服务配置异常,请稍后重试";
console.log("🔴 WebSocket握手失败服务器返回200而非101升级响应");
} else if (error.message.includes("unexpected response code: 404")) {
this.connectionError = "服务地址不可用,请稍后重试";
this.connectionError = this.$t("chat.serviceAddressUnavailable") || "服务地址不可用,请稍后重试";
console.log("🔴 WebSocket握手失败服务地址404");
} else if (error.message.includes("unexpected response code: 500")) {
this.connectionError = "服务器暂时不可用,请稍后重试";
this.connectionError = this.$t("chat.server500") || "服务器暂时不可用,请稍后重试";
console.log("🔴 WebSocket握手失败服务器500错误");
} else if (error.message.includes("connection refused")) {
this.connectionError = "无法连接到服务器,请稍后重试";
this.connectionError = this.$t("chat.connectionFailedService") || "无法连接到服务器,请稍后重试";
console.log("🔴 WebSocket握手失败连接被拒绝");
} else {
this.connectionError = "连接失败,请稍后重试";
this.connectionError = this.$t("chat.connectionFailed") || "连接失败,请稍后重试";
console.log("🔴 WebSocket握手失败", error.message);
}
@ -3073,7 +3111,7 @@ export default {
console.log("❌ 握手错误重连次数已达上限,停止重连");
this.isHandlingError = false;
this.showRefreshButton = true;
this.connectionError = "连接失败,请刷新页面重试";
this.connectionError = this.$t("chat.connectionFailed") || "连接失败,请刷新页面重试";
return;
}
@ -3089,7 +3127,7 @@ export default {
console.error("❌ 握手错误重连失败:", retryError);
this.isHandlingError = false;
this.connectionStatus = "error";
this.connectionError = "重连失败,请稍后重试";
this.connectionError = this.$t("chat.reconnectFailed") || "重连失败,请稍后重试";
});
}, 3000);
},
@ -3110,7 +3148,7 @@ export default {
// === ===
this.isWebSocketConnected = false;
this.connectionStatus = "error";
this.connectionError = "连接客服系统失败,请检查网络或稍后重试";
this.connectionError = this.$t("chat.connectionFailedCustomer") || "连接客服系统失败,请检查网络或稍后重试";
this.showRefreshButton = false;
// 1UI
setTimeout(() => {
@ -3129,7 +3167,7 @@ export default {
this.isWebSocketConnected = false;
// === ===
this.connectionStatus = "error";
this.connectionError = "连接客服系统失败,请检查网络或稍后重试";
this.connectionError = this.$t("chat.connectionFailedCustomer") || "连接客服系统失败,请检查网络或稍后重试";
this.showRefreshButton = false;
//
setTimeout(() => {
@ -3210,7 +3248,7 @@ export default {
);
} else {
console.error("登录处理最终失败,已达到最大重试次数");
this.$message.error("聊天功能初始化失败,请刷新页面");
// this.$message.error("");
}
}
}
@ -3825,7 +3863,7 @@ export default {
.network-status {
position: fixed;
top: 20px;
top: 80px;
right: 20px;
padding: 8px 16px;
border-radius: 4px;

View File

@ -91,7 +91,23 @@ export const ChatWidget_zh = {
emailError:"用户信息获取失败,请刷新页面重试",
refreshPage:"刷新页面",
reconnectSuccess:"重新连接成功",
},
sendMessageEmpty:"发送消息不能为空",
unableToSubscribe:"连接状态异常,刷新页面重试",
conflict:"连接异常,可能是多窗口冲突,请关闭其他窗口重试",
abnormal:"连接异常",
networkAnomaly:"网络连接异常",
customerServiceOffline:"客服离线,请登录账号发送留言消息",
contentMax:"超出发送内容大小限制,请删除部分内容(300字以内)",
failInSend:"发送失败,请重试",
connectionLimitError:"连接数已达上限,请关闭一些窗口后刷新重试",
serverBusy:"服务器繁忙,请稍后刷新重试",
connectionTimedOut:"连接超时,稍后重试...",
reconnectFailed:"重连失败,请稍后重试",
serviceConfigurationError:"服务配置异常,请稍后重试",
serviceAddressUnavailable:"服务地址不可用,请稍后重试",
connectionFailedService:"无法连接到服务器,请稍后重试",
connectionFailedCustomer:"连接客服系统失败,请检查网络或稍后重试",
},
}
@ -157,7 +173,7 @@ export const ChatWidget_en = {
None: "No messages",
sendPicture: "Send image",
inputMessage: "Type message, Enter to send, Ctrl+Enter for new line",
bottom: "Back to bottom",
bottom: "to bottom",
Preview: "Preview image",
chatRoom: "Chat room",
CLOSED: "Closed",
@ -190,7 +206,30 @@ export const ChatWidget_en = {
emailError:"Failed to get user information, please refresh page",
refreshPage:"Refresh page",
reconnectSuccess:"Reconnect successfully",
}
sendMessageEmpty:"Message cannot be empty",
unableToSubscribe:"Connection status abnormal, please refresh the page",
conflict:"Connection exception, possibly due to multiple window conflicts, please close other windows and try again",
abnormal:"Connection exception",
networkAnomaly:"Network connection exception",
customerServiceOffline:"Customer service offline, please login to send message",
contentMax:"Content exceeds the size limit, please delete some content(300 characters or less)",
failInSend:"Failed to send, please try again",
connectionLimitError:"Connection limit reached, please close some windows and refresh to try again",
serverBusy:"Server busy, please refresh later",
connectionTimedOut:"Connection timed out, please try again later",
reconnectFailed:"Reconnect failed, please try again later",
serviceConfigurationError:"Service configuration exception, please try again later",
serviceAddressUnavailable:"Service address unavailable, please try again later",
connectionFailedService:"Failed to connect to the server, please try again later",
connectionFailedCustomer:"Failed to connect to the customer service system, please check the network or try again later",
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1407,13 +1407,13 @@ export default {
// 其他CSS样式可以根据需要添加
},
handelProfitCalculation() {
for (const key in this.CalculatorData) {
if (!this.CalculatorData[key]) {
// this.$message({
// message: this.$t(`home.acquisitionFailed`),
// type: "error",
// });
if (this.CalculatorData[key]!==0 && !this.CalculatorData[key]) {
this.$message({
message: this.$t(`home.acquisitionFailed`),
type: "error",
});
this.profit = 0
// var myDiv = document.getElementById('myDiv');
// this.disableElement(myDiv);

View File

@ -680,6 +680,7 @@
:key="item.value"
:label="item.label"
:value="item.value"
v-show="item.value !== 'enx'"
>
<div style="display: flex; align-items: center">
<img :src="item.imgUrl" style="float: left; width: 20px" />

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -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.9eb6b4eb.js></script><script defer src=/js/app-d363ae0c.ec582e15.js></script><script defer src=/js/app-5c551db8.aa772a92.js></script><script defer src=/js/app-01dc9ae1.e746f05c.js></script><script defer src=/js/app-8e0489d9.cbdab613.js></script><script defer src=/js/app-72600b29.a3b71b37.js></script><script defer src=/js/app-f035d474.92e1d288.js></script><script defer src=/js/app-113c6c50.56b97e4e.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/app-189e7968.0fe23a85.css rel=stylesheet><link href=/css/app-01dc9ae1.04da7d85.css rel=stylesheet><link href=/css/app-8e0489d9.2416bb84.css rel=stylesheet><link href=/css/app-72600b29.0c194743.css rel=stylesheet><link href=/css/app-f035d474.0348646a.css rel=stylesheet><link href=/css/app-113c6c50.dfa1d227.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.f413248c.js></script><script defer src=/js/app-d363ae0c.ec582e15.js></script><script defer src=/js/app-5c551db8.6b412dd5.js></script><script defer src=/js/app-01dc9ae1.e746f05c.js></script><script defer src=/js/app-8e0489d9.3811f71f.js></script><script defer src=/js/app-72600b29.11174efb.js></script><script defer src=/js/app-f035d474.92e1d288.js></script><script defer src=/js/app-113c6c50.56b97e4e.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/app-189e7968.908e0479.css rel=stylesheet><link href=/css/app-01dc9ae1.04da7d85.css rel=stylesheet><link href=/css/app-8e0489d9.c5f430f0.css rel=stylesheet><link href=/css/app-72600b29.37eab263.css rel=stylesheet><link href=/css/app-f035d474.0348646a.css rel=stylesheet><link href=/css/app-113c6c50.dfa1d227.css rel=stylesheet></head><body><div id=app></div></body></html>

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -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-06-13T06:54:37.634Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-06-13T06:54:37.634Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-06-13T06:54:37.634Z</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-06-17T02:57:34.126Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-06-17T02:57:34.126Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>

Binary file not shown.

View File

@ -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-06-13T06:54:37.623Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-06-13T06:54:37.623Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-06-13T06:54:37.623Z</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-06-17T02:57:34.114Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-06-17T02:57:34.114Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>

Binary file not shown.