客服系统:1.滚动到列表下方分页请求历史用户列表拼接 完成 2.游客功能添加、删除列表离线游客 目前游客断开没有返回关闭信息 3.中英文翻译 处理中 4.客服页面添加回到底部功能 增加用户体验 完成
This commit is contained in:
parent
d3ac95af75
commit
38fbb4e625
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<router-view class="page" />
|
||||
<!-- <ChatWidget v-if="!$route.path.includes('/customerService')" /> -->
|
||||
<ChatWidget v-if="!$route.path.includes('/customerService')" />
|
||||
</div>
|
||||
</template>
|
||||
<script >
|
||||
|
|
|
@ -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();
|
||||
},
|
||||
|
@ -455,8 +519,8 @@ export default {
|
|||
|
||||
// 检查 WebSocket 连接状态
|
||||
if (!this.stompClient || !this.stompClient.connected) {
|
||||
console.log('发送消息时连接已断开,尝试重连...');
|
||||
this.$message.warning('连接已断开,正在重新连接...');
|
||||
console.log("发送消息时连接已断开,尝试重连...");
|
||||
this.$message.warning("连接已断开,正在重新连接...");
|
||||
this.handleDisconnect();
|
||||
return;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -638,7 +714,7 @@ export default {
|
|||
} finally {
|
||||
this.isLoadingHistory = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// 加载更多历史消息(超过7天的)
|
||||
async loadMoreHistory() {
|
||||
|
@ -648,9 +724,11 @@ export default {
|
|||
|
||||
try {
|
||||
// 获取当前消息列表中最旧消息的 ID
|
||||
const oldestMessage = this.messages.find(msg => !msg.isSystemHint && !msg.isLoading);
|
||||
const oldestMessage = this.messages.find(
|
||||
(msg) => !msg.isSystemHint && !msg.isLoading
|
||||
);
|
||||
if (!oldestMessage || !oldestMessage.id) {
|
||||
console.warn('没有找到有效的消息ID');
|
||||
console.warn("没有找到有效的消息ID");
|
||||
this.hasMoreHistory = false;
|
||||
return;
|
||||
}
|
||||
|
@ -669,7 +747,7 @@ export default {
|
|||
roomId: this.roomId,
|
||||
userType: this.userType,
|
||||
email: this.userEmail,
|
||||
id: oldestMessage.id // 添加最旧消息的 ID
|
||||
id: oldestMessage.id, // 添加最旧消息的 ID
|
||||
});
|
||||
|
||||
// 移除加载中提示
|
||||
|
@ -718,7 +796,7 @@ export default {
|
|||
} 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,
|
||||
|
@ -902,7 +980,10 @@ export default {
|
|||
this.determineUserType();
|
||||
|
||||
// 如果未连接或连接断开,则重新初始化 WebSocket
|
||||
if (!this.isWebSocketConnected || this.connectionStatus === "disconnected") {
|
||||
if (
|
||||
!this.isWebSocketConnected ||
|
||||
this.connectionStatus === "disconnected"
|
||||
) {
|
||||
await this.connectWebSocket();
|
||||
}
|
||||
|
||||
|
@ -924,7 +1005,7 @@ export default {
|
|||
this.$message.error("初始化聊天失败,请重试");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
minimizeChat() {
|
||||
this.isChatOpen = false;
|
||||
|
@ -1000,7 +1081,7 @@ export default {
|
|||
|
||||
const scrollOptions = {
|
||||
top: this.$refs.chatBody.scrollHeight,
|
||||
behavior: force ? 'auto' : 'smooth' // 强制滚动时使用 'auto'
|
||||
behavior: force ? "auto" : "smooth", // 强制滚动时使用 'auto'
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -1009,7 +1090,7 @@ export default {
|
|||
// 如果平滑滚动不支持,则直接设置
|
||||
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);
|
||||
|
@ -1215,6 +1281,23 @@ export default {
|
|||
}
|
||||
// 断开 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>
|
|
@ -10,6 +10,70 @@ export const ChatWidget_zh = {
|
|||
onlyImages:"只能上传图片文件!",
|
||||
imageTooLarge:"图片大小不能超过5MB!",
|
||||
imageReceived:"已收到您的图片,我们会尽快处理您的问题。",
|
||||
|
||||
networkError:"网络连接已断开,请刷新页面重试",
|
||||
openCustomerService:"打开客服聊天",
|
||||
connectToCustomerService:"正在连接客服系统...",
|
||||
connectionFailed:"连接失败,请刷新页面重试",
|
||||
tryConnectingAgain:"重试连接",
|
||||
loading:"加载中...",
|
||||
loadMore:"加载更多历史消息",
|
||||
welcomeToUse:"欢迎使用在线客服,请问有什么可以帮您?",
|
||||
picture:"聊天图片",
|
||||
read:"已读",
|
||||
unread:"未读",
|
||||
subscriptionFailed:"消息订阅失败,可能无法接收新消息",
|
||||
break:"连接断开",
|
||||
retry:"秒后重试",
|
||||
disconnectWaiting:"断线重连中...",
|
||||
sendFailed:"发送消息失败,请重试",
|
||||
noHistory:"暂无历史消息",
|
||||
historicalFailure:"加载历史消息失败,请重试",
|
||||
loadingHistory:"正在加载更多历史消息...",
|
||||
noMoreHistory:"没有更多历史消息了",
|
||||
Loaded:"已加载历史消息",
|
||||
newMessage:"新消息",
|
||||
pictureMessage:"图片消息",
|
||||
initializationFailed:"初始化失败,请刷新页面重试",
|
||||
beSorry:"抱歉,我暂时无法回答这个问题。请排队等待人工客服或提交工单。",
|
||||
today:"今天",
|
||||
yesterday:"昨天",
|
||||
canOnlyUploadImages:"只能上传图片文件!",
|
||||
imageSizeExceeded:"图片大小不能超过5MB!",
|
||||
uploading:"正在上传图片...",
|
||||
pictureFailed:"发送图片失败,请重试",
|
||||
readImage:"读取图片失败,请重试",
|
||||
processingFailed:"图片处理失败,请重试",
|
||||
Disconnected:"连接已断开",
|
||||
reconnecting:"正在重连...",
|
||||
contactList:"联系列表",
|
||||
search:"搜索最近联系人",
|
||||
tourist:"游客",
|
||||
important:"重要",
|
||||
markAsImportant:"标记为重要",
|
||||
cancelImportant:"已取消重要标记",
|
||||
markingFailed:"标记操作失败,请重试",
|
||||
select:"请选择联系人",
|
||||
notSelected:"您尚未选择联系人",
|
||||
None:"暂无消息记录",
|
||||
sendPicture:"发送图片",
|
||||
inputMessage:"请输入消息,按Enter键发送,按Ctrl+Enter键换行",
|
||||
bottom:"回到底部",
|
||||
Preview:"预览图片",
|
||||
chatRoom:"聊天室",
|
||||
CLOSED:"已关闭",
|
||||
picture2:"图片",
|
||||
Unnamed:"未命名聊天室",
|
||||
noNewsAtTheMoment:"暂无消息",
|
||||
contactFailed:"加载更多联系人失败",
|
||||
listException:"获取聊天室列表异常",
|
||||
my:"我",
|
||||
unknownSender:"未知发送者",
|
||||
recordFailed:"加载聊天记录失败",
|
||||
messageException:"加载消息异常",
|
||||
chooseFirst:"请先选择联系人",
|
||||
chatDisconnected:"聊天连接已断开,请刷新页面重试",
|
||||
pictureSuccessful:"图片已发送",
|
||||
},
|
||||
|
||||
|
||||
|
@ -28,5 +92,73 @@ export const ChatWidget_en = {
|
|||
onlyImages:"Only image files can be uploaded!",
|
||||
imageTooLarge:"The image size cannot exceed 5MB!",
|
||||
imageReceived:"We have received your image, and we will handle your question as soon as possible.",
|
||||
|
||||
networkError: "Network disconnected, please refresh page",
|
||||
openCustomerService: "Open customer service chat",
|
||||
connectToCustomerService: "Connecting to customer service...",
|
||||
connectionFailed: "Connection failed, please refresh page",
|
||||
tryConnectingAgain: "Retry connection",
|
||||
loading: "Loading...",
|
||||
loadMore: "Load more history",
|
||||
welcomeToUse: "Welcome to online service, how can I help you?",
|
||||
picture: "Chat image",
|
||||
read: "Read",
|
||||
unread: "Unread",
|
||||
subscriptionFailed: "Message subscription failed",
|
||||
break: "Connection lost",
|
||||
retry: "Retry in seconds",
|
||||
disconnectWaiting: "Reconnecting...",
|
||||
sendFailed: "Send failed, please retry",
|
||||
noHistory: "No history",
|
||||
historicalFailure: "Failed to load history",
|
||||
loadingHistory: "Loading more history...",
|
||||
noMoreHistory: "No more history",
|
||||
Loaded: "History loaded",
|
||||
newMessage: "New message",
|
||||
pictureMessage: "Image message",
|
||||
initializationFailed: "Initialization failed, please refresh",
|
||||
beSorry: "Sorry, I cannot answer this. Please wait for agent or submit ticket",
|
||||
today: "Today",
|
||||
yesterday: "Yesterday",
|
||||
canOnlyUploadImages: "Only image files allowed",
|
||||
imageSizeExceeded: "Image size exceeds 5MB",
|
||||
uploading: "Uploading image...",
|
||||
pictureFailed: "Failed to send image",
|
||||
readImage: "Failed to read image",
|
||||
processingFailed: "Image processing failed",
|
||||
Disconnected: "Disconnected",
|
||||
reconnecting: "Reconnecting...",
|
||||
contactList: "Contact list",
|
||||
search: "Search contacts",
|
||||
tourist: "Guest",
|
||||
important: "Important",
|
||||
markAsImportant: "Mark as important",
|
||||
cancelImportant: "Unmarked as important",
|
||||
markingFailed: "Marking failed",
|
||||
select: "Select contact",
|
||||
notSelected: "No contact selected",
|
||||
None: "No messages",
|
||||
sendPicture: "Send image",
|
||||
inputMessage: "Type message, Enter to send, Ctrl+Enter for new line",
|
||||
bottom: "Back to bottom",
|
||||
Preview: "Preview image",
|
||||
chatRoom: "Chat room",
|
||||
CLOSED: "Closed",
|
||||
picture2: "Image",
|
||||
Unnamed: "Unnamed chat",
|
||||
noNewsAtTheMoment: "No messages",
|
||||
contactFailed: "Failed to load contacts",
|
||||
listException: "Failed to get chat list",
|
||||
my: "Me",
|
||||
unknownSender: "Unknown sender",
|
||||
recordFailed: "Failed to load chat records",
|
||||
messageException: "Failed to load messages",
|
||||
chooseFirst: "Please select contact first",
|
||||
chatDisconnected: "Chat disconnected, please refresh",
|
||||
pictureSuccessful: "Image sent",
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,5 +1,10 @@
|
|||
<template>
|
||||
<div class="cs-chat-container">
|
||||
<!-- 添加连接状态提示 -->
|
||||
<div v-if="connectionStatus !== 'connected'" class="connection-status" :class="connectionStatus">
|
||||
<i :class="connectionStatus === 'error' ? 'el-icon-warning' : 'el-icon-loading'"></i>
|
||||
<span>{{ connectionStatus === 'error' ? '连接已断开' : '正在连接...' }}</span>
|
||||
</div>
|
||||
<!-- 聊天窗口主体 -->
|
||||
<div class="cs-chat-wrapper">
|
||||
<!-- 左侧联系人列表 -->
|
||||
|
@ -22,6 +27,7 @@
|
|||
class="cs-contact-item"
|
||||
:class="{ active: currentContactId === contact.roomId }"
|
||||
@click="selectContact(contact.roomId)"
|
||||
:title="contact.name"
|
||||
>
|
||||
<div class="cs-avatar">
|
||||
<i class="iconfont icon-icon28" style="font-size: 2vw"></i>
|
||||
|
@ -104,7 +110,11 @@
|
|||
</div>
|
||||
|
||||
<!-- 聊天内容区域 -->
|
||||
<div class="cs-chat-messages" ref="messageContainer">
|
||||
<div
|
||||
class="cs-chat-messages"
|
||||
ref="messageContainer"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<div v-if="!currentContact" class="cs-empty-chat">
|
||||
<i class="el-icon-chat-dot-round"></i>
|
||||
<p>您尚未选择联系人</p>
|
||||
|
@ -120,6 +130,8 @@
|
|||
text-align: center;
|
||||
color: #409eff;
|
||||
margin-bottom: 10px;
|
||||
font-size: 0.7vw;
|
||||
|
||||
"
|
||||
>
|
||||
<i class="el-icon-arrow-up"></i>
|
||||
|
@ -222,6 +234,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div
|
||||
v-if="showScrollButton"
|
||||
class="scroll-to-bottom"
|
||||
@click="scrollToBottom(true)"
|
||||
>
|
||||
回到底部 <i class="el-icon-arrow-down"></i>
|
||||
</div>
|
||||
|
||||
<!-- 图片预览 -->
|
||||
<el-dialog
|
||||
:visible.sync="previewVisible"
|
||||
|
@ -285,6 +308,16 @@ export default {
|
|||
chatRooms: [], // 初始化聊天室列表数组
|
||||
isWebSocketConnected: false,
|
||||
connectionStatus: "disconnected",
|
||||
isLoadingMoreContacts: false, // 是否正在加载更多联系人
|
||||
lastContactTime: null, // 最后一个联系人的时间
|
||||
showScrollButton: false,
|
||||
visibilityHandler: null, // 页面可见性处理器
|
||||
reconnectTimer: null, // 重连定时器
|
||||
maxReconnectAttempts: 5, // 最大重连次数
|
||||
reconnectInterval: 5000, // 重连间隔(ms)
|
||||
reconnectAttempts: 0, // 当前重连次数
|
||||
lastActivityTime: Date.now(), // 最后活动时间
|
||||
activityCheckInterval: null, // 活动检测定时器
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -342,7 +375,6 @@ export default {
|
|||
window.addEventListener("setItem", () => {
|
||||
let userEmail = localStorage.getItem("userEmail");
|
||||
this.userEmail = JSON.parse(userEmail);
|
||||
|
||||
});
|
||||
// 确保初始加载后滚动到底部
|
||||
this.$nextTick(() => {
|
||||
|
@ -357,6 +389,25 @@ export default {
|
|||
);
|
||||
}
|
||||
});
|
||||
// 添加联系人列表滚动事件监听
|
||||
this.$nextTick(() => {
|
||||
const contactList = document.querySelector(".cs-contacts");
|
||||
if (contactList) {
|
||||
contactList.addEventListener("scroll", this.handleContactListScroll);
|
||||
}
|
||||
});
|
||||
|
||||
// 添加页面可见性监听
|
||||
this.visibilityHandler = () => {
|
||||
if (document.visibilityState === "visible") {
|
||||
// 页面变为可见时,检查连接状态
|
||||
this.checkAndReconnect();
|
||||
}
|
||||
};
|
||||
document.addEventListener("visibilitychange", this.visibilityHandler);
|
||||
|
||||
// 添加用户活动检测
|
||||
this.startActivityCheck();
|
||||
},
|
||||
methods: {
|
||||
handleKeyDown(e) {
|
||||
|
@ -399,20 +450,24 @@ export default {
|
|||
type: this.userType,
|
||||
};
|
||||
|
||||
// 添加重连逻辑
|
||||
this.stompClient.connect(
|
||||
headers,
|
||||
(frame) => {
|
||||
console.log("[客服系统] WebSocket 连接成功", frame);
|
||||
console.log('[客服系统] WebSocket 连接成功', frame);
|
||||
this.isWebSocketConnected = true;
|
||||
this.connectionStatus = "connected";
|
||||
this.connectionStatus = 'connected';
|
||||
this.reconnectAttempts = 0;
|
||||
this.subscribeToMessages();
|
||||
this.updateLastActivityTime();
|
||||
},
|
||||
(error) => {
|
||||
console.error("[客服系统] WebSocket 错误:", error);
|
||||
console.error('[客服系统] WebSocket 错误:', error);
|
||||
this.handleDisconnect();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// 配置心跳
|
||||
this.stompClient.heartbeat.outgoing = 20000;
|
||||
this.stompClient.heartbeat.incoming = 20000;
|
||||
|
@ -435,23 +490,68 @@ export default {
|
|||
id: `customer_${this.userEmail}`,
|
||||
}
|
||||
);
|
||||
// this.stompClient.subscribe(
|
||||
// `/user/queue/customer_service`, // 修改为客服专用的订阅路径
|
||||
// this.handleIncomingMessage,
|
||||
// {
|
||||
// id: `customer_service_${this.userEmail}`,
|
||||
// }
|
||||
// );
|
||||
|
||||
// 订阅聊天室关闭消息
|
||||
this.stompClient.subscribe(
|
||||
`/sub/queue/close/room/${this.userEmail}`,
|
||||
this.handleRoomClose,
|
||||
|
||||
);
|
||||
|
||||
console.log(
|
||||
"CustomerService 成功订阅消息频道:",
|
||||
`/sub/queue/customer/${this.userEmail}`
|
||||
);
|
||||
|
||||
console.log(
|
||||
"CustomerService 成功订阅关闭消息频道:",
|
||||
`/sub/queue/close/room/${this.userEmail}`
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("CustomerService 订阅消息失败:", error);
|
||||
}
|
||||
},
|
||||
|
||||
// 处理聊天室关闭的方法 删除游客
|
||||
handleRoomClose(message) {
|
||||
try {
|
||||
// 获取需要关闭的游客邮箱
|
||||
const closedUserEmail = message.body;
|
||||
console.log("收到聊天室关闭通知:", closedUserEmail);
|
||||
|
||||
// 在联系人列表中查找对应的聊天室
|
||||
const contactIndex = this.contacts.findIndex(
|
||||
(contact) => contact.name === closedUserEmail
|
||||
);
|
||||
|
||||
if (contactIndex !== -1) {
|
||||
// 如果当前选中的就是被关闭的聊天室,需要清除选中状态
|
||||
if (this.currentContactId === this.contacts[contactIndex].roomId) {
|
||||
this.currentContactId = null;
|
||||
}
|
||||
|
||||
// 从联系人列表中移除
|
||||
this.contacts.splice(contactIndex, 1);
|
||||
|
||||
// 从消息列表中移除
|
||||
this.$delete(this.messages, this.contacts[contactIndex].roomId);
|
||||
|
||||
// 从手动创建的聊天室列表中移除
|
||||
const manualRoomIndex = this.manualCreatedRooms.findIndex(
|
||||
(room) => room.name === closedUserEmail
|
||||
);
|
||||
if (manualRoomIndex !== -1) {
|
||||
this.manualCreatedRooms.splice(manualRoomIndex, 1);
|
||||
this.saveManualCreatedRooms();
|
||||
}
|
||||
|
||||
this.$message.info(`聊天室 ${closedUserEmail} 已关闭`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("处理聊天室关闭消息失败:", error);
|
||||
}
|
||||
},
|
||||
|
||||
// 断开连接
|
||||
disconnectWebSocket() {
|
||||
if (this.stompClient) {
|
||||
|
@ -476,16 +576,51 @@ export default {
|
|||
// 处理断开连接
|
||||
handleDisconnect() {
|
||||
this.isWebSocketConnected = false;
|
||||
this.connectionStatus = "error";
|
||||
this.connectionStatus = 'error';
|
||||
|
||||
// 尝试重新连接
|
||||
setTimeout(() => {
|
||||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||||
this.reconnectAttempts++;
|
||||
console.log(`尝试重新连接 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
|
||||
|
||||
this.reconnectTimer = setTimeout(() => {
|
||||
if (!this.isWebSocketConnected) {
|
||||
this.initWebSocket();
|
||||
}
|
||||
}, 5000);
|
||||
}, this.reconnectInterval);
|
||||
} else {
|
||||
console.log('达到最大重连次数,停止重连');
|
||||
this.$message.error('连接已断开,请刷新页面重试');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 检查并重连
|
||||
async checkAndReconnect() {
|
||||
if (!this.isWebSocketConnected) {
|
||||
console.log('页面恢复可见,尝试重新连接...');
|
||||
await this.initWebSocket();
|
||||
}
|
||||
},
|
||||
|
||||
// 开始活动检测
|
||||
startActivityCheck() {
|
||||
this.activityCheckInterval = setInterval(() => {
|
||||
const now = Date.now();
|
||||
const inactiveTime = now - this.lastActivityTime;
|
||||
|
||||
// 如果超过5分钟没有活动,断开连接
|
||||
if (inactiveTime > 5 * 60 * 1000) {
|
||||
this.disconnectWebSocket();
|
||||
}
|
||||
}, 60000); // 每分钟检查一次
|
||||
},
|
||||
|
||||
// 更新最后活动时间
|
||||
updateLastActivityTime() {
|
||||
this.lastActivityTime = Date.now();
|
||||
},
|
||||
|
||||
|
||||
// 获取当前的 UTC 时间
|
||||
getUTCTime() {
|
||||
const now = new Date();
|
||||
|
@ -610,7 +745,9 @@ export default {
|
|||
this.$set(this.messages, messageData.roomId, []);
|
||||
} else {
|
||||
// 如果聊天室已存在,更新最后一条消息
|
||||
existingContact.lastMessage = messageData.isImage ? "[图片]" : messageData.content;
|
||||
existingContact.lastMessage = messageData.isImage
|
||||
? "[图片]"
|
||||
: messageData.content;
|
||||
existingContact.lastTime = messageData.time;
|
||||
}
|
||||
|
||||
|
@ -631,12 +768,15 @@ export default {
|
|||
roomId: messageData.roomId,
|
||||
});
|
||||
|
||||
// 如果是当前选中的聊天室,标记为已读
|
||||
// 如果是当前选中的聊天室,强制滚动到底部
|
||||
if (messageData.roomId === this.currentContactId) {
|
||||
this.markMessagesAsRead(messageData.roomId);
|
||||
this.scrollToBottom(true); // 使用强制滚动
|
||||
} else {
|
||||
// 更新未读消息数
|
||||
const contact = this.contacts.find((c) => c.roomId === messageData.roomId);
|
||||
const contact = this.contacts.find(
|
||||
(c) => c.roomId === messageData.roomId
|
||||
);
|
||||
if (contact) {
|
||||
contact.unread = (contact.unread || 0) + 1;
|
||||
}
|
||||
|
@ -647,8 +787,113 @@ export default {
|
|||
} catch (error) {
|
||||
console.error("处理新消息失败:", error);
|
||||
}
|
||||
},
|
||||
},
|
||||
// 处理联系人列表滚动
|
||||
handleContactListScroll(e) {
|
||||
const container = e.target;
|
||||
// 判断是否滚动到底部(允许2px的误差)
|
||||
if (
|
||||
container.scrollHeight - container.scrollTop - container.clientHeight <
|
||||
2
|
||||
) {
|
||||
this.loadMoreContacts();
|
||||
}
|
||||
},
|
||||
|
||||
// 加载更多联系人
|
||||
async loadMoreContacts() {
|
||||
// 防止重复加载
|
||||
if (this.isLoadingMoreContacts) return;
|
||||
|
||||
// 获取最后一个联系人
|
||||
const lastContact = this.contacts[this.contacts.length - 1];
|
||||
if (!lastContact) return;
|
||||
|
||||
this.isLoadingMoreContacts = true;
|
||||
|
||||
try {
|
||||
const formatDateTime = (date) => {
|
||||
if (!date) return null;
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(d.getDate()).padStart(2, "0");
|
||||
const hours = String(d.getHours()).padStart(2, "0");
|
||||
const minutes = String(d.getMinutes()).padStart(2, "0");
|
||||
const seconds = String(d.getSeconds()).padStart(2, "0");
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
};
|
||||
// 构建请求参数
|
||||
const requestData = {
|
||||
sendDateTime: formatDateTime(lastContact.lastTime),
|
||||
|
||||
userType: 2, // 客服类型
|
||||
email: this.userEmail,
|
||||
};
|
||||
|
||||
const response = await getRoomList(requestData);
|
||||
|
||||
if (response?.code === 200 && response.rows?.length > 0) {
|
||||
// 处理新获取的联系人数据
|
||||
const newContacts = response.rows.map((room) => {
|
||||
const existingContact = this.contacts.find(
|
||||
(c) => c.roomId === room.id
|
||||
);
|
||||
const manualRoom = this.manualCreatedRooms.find(
|
||||
(c) => c.roomId === room.id
|
||||
);
|
||||
|
||||
const isImportant =
|
||||
room.flag === 1
|
||||
? true
|
||||
: room.flag === 0
|
||||
? false
|
||||
: room.important === 1
|
||||
? true
|
||||
: existingContact
|
||||
? existingContact.important
|
||||
: false;
|
||||
|
||||
return {
|
||||
roomId: room.id,
|
||||
name: room.userEmail || "未命名聊天室",
|
||||
avatar: this.getDefaultAvatar(room.roomName || "未命名聊天室"),
|
||||
lastMessage:
|
||||
room.lastMessage ||
|
||||
(existingContact ? existingContact.lastMessage : "暂无消息"),
|
||||
lastTime: room.lastUserSendTime
|
||||
? new Date(room.lastUserSendTime)
|
||||
: new Date(),
|
||||
unread: existingContact?.unread ?? room.unreadCount ?? 0,
|
||||
important: isImportant,
|
||||
isManualCreated: manualRoom ? true : false,
|
||||
sendUserType: room.sendUserType,
|
||||
isGuest: room.sendUserType === 0,
|
||||
};
|
||||
});
|
||||
|
||||
// 过滤掉已存在的联系人
|
||||
const uniqueNewContacts = newContacts.filter(
|
||||
(newContact) =>
|
||||
!this.contacts.some(
|
||||
(existingContact) =>
|
||||
existingContact.roomId === newContact.roomId
|
||||
)
|
||||
);
|
||||
|
||||
// 添加新联系人
|
||||
if (uniqueNewContacts.length > 0) {
|
||||
this.contacts = [...this.contacts, ...uniqueNewContacts];
|
||||
this.sortContacts();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("加载更多联系人失败:", error);
|
||||
this.$message.error("加载更多联系人失败");
|
||||
} finally {
|
||||
this.isLoadingMoreContacts = false;
|
||||
}
|
||||
},
|
||||
// 处理新聊天室创建
|
||||
handleNewChatRoom(messageData) {
|
||||
// 检查是否已存在该聊天室
|
||||
|
@ -832,7 +1077,13 @@ export default {
|
|||
async fetchRoomList() {
|
||||
try {
|
||||
this.loadingRooms = true;
|
||||
const response = await getRoomList();
|
||||
const requestData = {
|
||||
lastTime: null, // 首次加载不传时间
|
||||
userType: 2,
|
||||
email: this.userEmail,
|
||||
};
|
||||
|
||||
const response = await getRoomList(requestData);
|
||||
if (response?.code === 200) {
|
||||
const newContacts = response.rows.map((room) => {
|
||||
const existingContact = this.contacts.find(
|
||||
|
@ -858,8 +1109,9 @@ export default {
|
|||
roomId: room.id,
|
||||
name: room.userEmail || "未命名聊天室",
|
||||
avatar: this.getDefaultAvatar(room.roomName || "未命名聊天室"),
|
||||
// 修改这里:优先使用服务器返回的消息,其次是现有联系人的消息
|
||||
lastMessage: room.lastMessage || (existingContact ? existingContact.lastMessage : "暂无消息"),
|
||||
lastMessage:
|
||||
room.lastMessage ||
|
||||
(existingContact ? existingContact.lastMessage : "暂无消息"),
|
||||
lastTime: room.lastUserSendTime
|
||||
? new Date(room.lastUserSendTime)
|
||||
: new Date(),
|
||||
|
@ -881,7 +1133,7 @@ export default {
|
|||
} finally {
|
||||
this.loadingRooms = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// 加载更多历史消息
|
||||
async loadMoreHistory() {
|
||||
|
@ -1047,7 +1299,9 @@ export default {
|
|||
const message = {
|
||||
id: messageData.id || Date.now(), // 如果没有id则使用时间戳
|
||||
sender: messageData.sender,
|
||||
avatar: messageData.avatar || (messageData.isSelf ? "iconfont icon-icon28" : "iconfont icon-user"),
|
||||
avatar:
|
||||
messageData.avatar ||
|
||||
(messageData.isSelf ? "iconfont icon-icon28" : "iconfont icon-user"),
|
||||
content: messageData.content,
|
||||
time: messageData.time || new Date(),
|
||||
isSelf: messageData.isSelf,
|
||||
|
@ -1073,7 +1327,7 @@ export default {
|
|||
this.scrollToBottom();
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
// 处理图片上传
|
||||
async handleImageUpload(event) {
|
||||
// 检查是否有选中的联系人和 WebSocket 连接
|
||||
|
@ -1142,7 +1396,7 @@ export default {
|
|||
this.updateContactLastMessage({
|
||||
roomId: this.currentContactId,
|
||||
content: "[图片]",
|
||||
isImage: true
|
||||
isImage: true,
|
||||
});
|
||||
|
||||
this.$message.success("图片已发送");
|
||||
|
@ -1155,7 +1409,6 @@ export default {
|
|||
|
||||
// 开始读取文件
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
} catch (error) {
|
||||
console.error("上传图片异常:", error);
|
||||
this.$message.error("上传图片失败,请重试");
|
||||
|
@ -1164,9 +1417,7 @@ export default {
|
|||
// 清空文件选择器
|
||||
this.$refs.imageInput.value = "";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
},
|
||||
|
||||
// 更新联系人最后一条消息
|
||||
updateContactLastMessage(message) {
|
||||
|
@ -1249,14 +1500,24 @@ export default {
|
|||
},
|
||||
|
||||
// 滚动到底部
|
||||
scrollToBottom() {
|
||||
scrollToBottom(force = false) {
|
||||
const container = this.$refs.messageContainer;
|
||||
if (!container) return;
|
||||
|
||||
// 使用平滑滚动
|
||||
// 使用 nextTick 确保 DOM 更新后再滚动
|
||||
this.$nextTick(() => {
|
||||
// 添加一个小延时确保内容完全渲染
|
||||
setTimeout(() => {
|
||||
container.scrollTo({
|
||||
top: container.scrollHeight,
|
||||
behavior: "smooth",
|
||||
behavior: force ? "auto" : "smooth",
|
||||
});
|
||||
|
||||
// 滚动完成后隐藏按钮
|
||||
if (force) {
|
||||
this.showScrollButton = false;
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -1363,6 +1624,12 @@ export default {
|
|||
},
|
||||
// 处理滚动事件
|
||||
handleScroll() {
|
||||
const container = this.$refs.messageContainer;
|
||||
if (!container) return;
|
||||
|
||||
// 如果不在底部,显示滚动按钮
|
||||
this.showScrollButton = !this.isAtBottom();
|
||||
|
||||
// 如果滚动到底部,重置标记
|
||||
if (this.isAtBottom()) {
|
||||
this.userViewHistory = false;
|
||||
|
@ -1455,9 +1722,7 @@ export default {
|
|||
// 组件销毁前断开连接
|
||||
this.disconnectWebSocket();
|
||||
|
||||
// if (this.roomListInterval) {
|
||||
// clearInterval(this.roomListInterval);
|
||||
// }
|
||||
|
||||
|
||||
// 移除滚动事件监听
|
||||
if (this.$refs.messageContainer) {
|
||||
|
@ -1466,12 +1731,25 @@ export default {
|
|||
this.handleScroll
|
||||
);
|
||||
}
|
||||
|
||||
// 清理新增的资源
|
||||
if (this.visibilityHandler) {
|
||||
document.removeEventListener('visibilitychange', this.visibilityHandler);
|
||||
}
|
||||
|
||||
if (this.activityCheckInterval) {
|
||||
clearInterval(this.activityCheckInterval);
|
||||
}
|
||||
|
||||
if (this.reconnectTimer) {
|
||||
clearTimeout(this.reconnectTimer);
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.cs-chat-container {
|
||||
width: 70%;
|
||||
width: 65%;
|
||||
height: 600px;
|
||||
margin: 0 auto;
|
||||
background-color: #f5f6f7;
|
||||
|
@ -1481,6 +1759,7 @@ export default {
|
|||
margin-top: 50px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.cs-chat-wrapper {
|
||||
|
@ -1490,12 +1769,14 @@ export default {
|
|||
|
||||
/* 联系人列表样式 */
|
||||
.cs-contact-list {
|
||||
width: 260px;
|
||||
width: 290px;
|
||||
min-width: 260px; /* 添加最小宽度 */
|
||||
border-right: 1px solid #e0e0e0;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden; /* 防止整体出现滚动条 */
|
||||
}
|
||||
|
||||
.cs-header {
|
||||
|
@ -1533,9 +1814,11 @@ export default {
|
|||
background-color: #e6f7ff;
|
||||
}
|
||||
|
||||
/* 修改头像区域样式 */
|
||||
.cs-avatar {
|
||||
position: relative;
|
||||
margin-right: 10px;
|
||||
flex-shrink: 0; /* 防止头像被压缩 */
|
||||
}
|
||||
|
||||
.unread-badge {
|
||||
|
@ -1555,7 +1838,8 @@ export default {
|
|||
|
||||
.cs-contact-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
min-width: 0; /* 允许内容收缩 */
|
||||
overflow: hidden; /* 防止内容溢出 */
|
||||
}
|
||||
|
||||
.cs-contact-name {
|
||||
|
@ -1565,6 +1849,9 @@ export default {
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 4px;
|
||||
white-space: nowrap; /* 防止换行 */
|
||||
overflow: hidden; /* 隐藏溢出内容 */
|
||||
text-overflow: ellipsis; /* 显示省略号 */
|
||||
}
|
||||
|
||||
.cs-contact-time {
|
||||
|
@ -1579,6 +1866,7 @@ export default {
|
|||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%; /* 限制最大宽度 */
|
||||
}
|
||||
|
||||
.important-tag {
|
||||
|
@ -1629,6 +1917,8 @@ export default {
|
|||
padding: 15px;
|
||||
overflow-y: auto;
|
||||
background-color: #f5f5f5;
|
||||
height: calc(100% - 180px); /* 减去头部和输入框的高度 */
|
||||
position: relative; /* 添加相对定位 */
|
||||
}
|
||||
|
||||
.cs-loading,
|
||||
|
@ -1648,9 +1938,11 @@ export default {
|
|||
color: #dcdfe6;
|
||||
}
|
||||
|
||||
/* 确保消息列表正确显示 */
|
||||
.cs-message-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 20px; /* 添加底部间距 */
|
||||
}
|
||||
|
||||
.cs-message {
|
||||
|
@ -1678,6 +1970,7 @@ export default {
|
|||
margin-left: 10px;
|
||||
}
|
||||
|
||||
/* 调整消息气泡样式 */
|
||||
.cs-bubble {
|
||||
max-width: 70%;
|
||||
padding: 8px 12px;
|
||||
|
@ -1685,6 +1978,7 @@ export default {
|
|||
background-color: #fff;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
margin-bottom: 4px; /* 添加消息间距 */
|
||||
}
|
||||
|
||||
.cs-message-self .cs-bubble {
|
||||
|
@ -1703,11 +1997,13 @@ export default {
|
|||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* 确保图片消息正确显示 */
|
||||
.cs-image img {
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: block; /* 确保图片正确显示 */
|
||||
}
|
||||
|
||||
/* 输入区域样式 */
|
||||
|
@ -1780,7 +2076,7 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
/* 添加重要标记样式 */
|
||||
/* 重要标记图标样式 */
|
||||
.important-star {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -1789,8 +2085,9 @@ export default {
|
|||
height: 30px;
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
color: #c0c4cc; /* 默认灰色 */
|
||||
color: #c0c4cc;
|
||||
transition: color 0.3s;
|
||||
flex-shrink: 0; /* 防止图标被压缩 */
|
||||
}
|
||||
|
||||
.important-star:hover {
|
||||
|
@ -1812,7 +2109,9 @@ export default {
|
|||
cursor: pointer;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
transition: background-color 0.2s;
|
||||
align-items: center; /* 确保垂直居中 */
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
box-sizing: border-box; /* 确保padding不会导致溢出 */
|
||||
}
|
||||
|
||||
/* 重要标签的样式调整 */
|
||||
|
@ -1842,4 +2141,58 @@ export default {
|
|||
.cs-contact-item.is-guest {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
/* 滚动按钮样式 */
|
||||
.scroll-to-bottom {
|
||||
position: absolute; /* 改为 fixed 定位 */
|
||||
right: 4px; /* 根据容器宽度调整位置 */
|
||||
bottom: 184px;
|
||||
background-color: #fff;
|
||||
border-radius: 5px 0px 0px 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
transition: all 0.3s;
|
||||
z-index: 1000; /* 确保按钮在最上层 */
|
||||
padding: 5px 1vw;
|
||||
font-size: 0.7vw;
|
||||
color: #7638ff;
|
||||
}
|
||||
|
||||
.scroll-to-bottom:hover {
|
||||
background-color: #f0f0f0;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.scroll-to-bottom i {
|
||||
font-size: 0.8vw;
|
||||
color: #7638ff;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
/* 添加连接状态样式 */
|
||||
.connection-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);
|
||||
}
|
||||
|
||||
.connection-status.error {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.connection-status.connecting {
|
||||
background-color: #f0f9eb;
|
||||
color: #67c23a;
|
||||
}
|
||||
</style>
|
|
@ -800,6 +800,7 @@ export default {
|
|||
.view{
|
||||
color: #5721e4;
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -826,6 +827,7 @@ export default {
|
|||
// overflow: hidden;
|
||||
padding: 5px 5px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
// background: palegoldenrod;
|
||||
|
||||
img {
|
||||
|
@ -841,7 +843,13 @@ export default {
|
|||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
.moveCurrencyBox li:hover {
|
||||
box-shadow: 0px 0px 5px 2px #d2c3ea;
|
||||
}
|
||||
|
||||
.currencySelect{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -1330,6 +1338,7 @@ export default {
|
|||
.view{
|
||||
color: #5721e4;
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1359,6 +1368,7 @@ export default {
|
|||
padding: 5px 5px;
|
||||
box-sizing: border-box;
|
||||
// background: palegoldenrod;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 25px;
|
||||
|
@ -1373,6 +1383,12 @@ export default {
|
|||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.moveCurrencyBox li:hover {
|
||||
box-shadow: 0px 0px 5px 2px #d2c3ea;
|
||||
}
|
||||
.currencySelect{
|
||||
display: flex;
|
||||
|
@ -3269,6 +3285,7 @@ export default {
|
|||
cursor: pointer;
|
||||
margin-left: 8px;
|
||||
color: #6E3EDB;
|
||||
// background: palegoldenrod;
|
||||
|
||||
}
|
||||
.view:hover{
|
||||
|
|
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.
|
@ -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>
|
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.
|
@ -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.
Loading…
Reference in New Issue