取消enx活动图片 费率改为1%
This commit is contained in:
parent
4d436c725e
commit
368d0a8a10
|
@ -1,16 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<router-view class="page" />
|
<router-view class="page" />
|
||||||
|
<!-- <ChatWidget /> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script >
|
<script >
|
||||||
|
import ChatWidget from '../src/components/ChatWidget.vue';
|
||||||
import { Debounce, throttle } from '@/utils/publicMethods';
|
import { Debounce, throttle } from '@/utils/publicMethods';
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
ChatWidget
|
||||||
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
//历史聊天记录查询 用户查询七天前的聊天信息
|
||||||
|
export function getHistory() {
|
||||||
|
return request({
|
||||||
|
url: `chat/message/find/history/message`,
|
||||||
|
method: 'get',
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//历史聊天记录查询 查询七天内记录
|
||||||
|
export function getHistory7() {
|
||||||
|
return request({
|
||||||
|
url: `chat/message/find/recently/message`,
|
||||||
|
method: 'get',
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//用户点击对话框默认已读
|
||||||
|
export function getReadMessage(data) {
|
||||||
|
return request({
|
||||||
|
url: `chat/message/read/message`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//聊天列表
|
||||||
|
export function getRoomList() {
|
||||||
|
return request({
|
||||||
|
url: `/chat/rooms/find/room/list`,
|
||||||
|
method: 'get',
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//重要聊天标记
|
||||||
|
export function getUpdateRoom(data) {
|
||||||
|
return request({
|
||||||
|
url: `/chat/rooms/update/room`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//图片上传接口
|
||||||
|
export function getFileUpdate(data) {
|
||||||
|
return request({
|
||||||
|
url: `file/update`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//图根据当前用户邮箱查询聊天室id
|
||||||
|
export function getUserid() {
|
||||||
|
return request({
|
||||||
|
url: `chat/rooms/find/room/by/userid`,
|
||||||
|
method: 'get',
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,893 @@
|
||||||
|
<template>
|
||||||
|
<div class="chat-widget">
|
||||||
|
<!-- 聊天图标 -->
|
||||||
|
<div
|
||||||
|
class="chat-icon"
|
||||||
|
@click="toggleChat"
|
||||||
|
:class="{ active: isChatOpen }"
|
||||||
|
aria-label="打开客服聊天"
|
||||||
|
tabindex="0"
|
||||||
|
@keydown.enter="toggleChat"
|
||||||
|
@keydown.space="toggleChat"
|
||||||
|
>
|
||||||
|
<i class="el-icon-chat-dot-round"></i>
|
||||||
|
<span v-if="unreadMessages > 0" class="unread-badge">{{
|
||||||
|
unreadMessages
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 聊天对话框 -->
|
||||||
|
<transition name="chat-slide">
|
||||||
|
<div v-show="isChatOpen" class="chat-dialog">
|
||||||
|
<div class="chat-header">
|
||||||
|
<div class="chat-title">{{ $t("chat.title") || "在线客服" }}</div>
|
||||||
|
<div class="chat-actions">
|
||||||
|
<i class="el-icon-minus" @click="minimizeChat"></i>
|
||||||
|
<i class="el-icon-close" @click="closeChat"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chat-body" ref="chatBody">
|
||||||
|
<!-- 连接状态提示 -->
|
||||||
|
<div v-if="connectionStatus === 'connecting'" class="chat-status connecting">
|
||||||
|
<i class="el-icon-loading"></i>
|
||||||
|
<p>正在连接客服系统...</p>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="connectionStatus === 'error'" class="chat-status error">
|
||||||
|
<i class="el-icon-warning"></i>
|
||||||
|
<p>连接失败,请稍后重试</p>
|
||||||
|
<button @click="connectWebSocket" class="retry-button">重试连接</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 消息列表 -->
|
||||||
|
<template v-else>
|
||||||
|
<div v-if="messages.length === 0" class="chat-empty">
|
||||||
|
{{ $t("chat.welcome") || "欢迎使用在线客服,请问有什么可以帮您?" }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="(msg, index) in messages"
|
||||||
|
:key="index"
|
||||||
|
class="chat-message"
|
||||||
|
:class="{
|
||||||
|
'chat-message-user': msg.type === 'user',
|
||||||
|
'chat-message-system': msg.type === 'system',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="message-avatar">
|
||||||
|
<i v-if="msg.type === 'system'" class="el-icon-service"></i>
|
||||||
|
<i v-else class="el-icon-user"></i>
|
||||||
|
</div>
|
||||||
|
<div class="message-content">
|
||||||
|
<!-- 文本消息 -->
|
||||||
|
<div v-if="!msg.isImage" class="message-text">{{ msg.text }}</div>
|
||||||
|
|
||||||
|
<!-- 图片消息 -->
|
||||||
|
<div v-else class="message-image">
|
||||||
|
<img :src="msg.imageUrl" @click="previewImage(msg.imageUrl)" alt="聊天图片" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="message-time">{{ formatTime(msg.time) }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-footer">
|
||||||
|
<div class="chat-toolbar">
|
||||||
|
<label for="imageUpload" class="image-upload-label" :class="{ 'disabled': connectionStatus !== 'connected' }">
|
||||||
|
<i class="el-icon-picture-outline"></i>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
id="imageUpload"
|
||||||
|
ref="imageUpload"
|
||||||
|
accept="image/*"
|
||||||
|
@change="handleImageUpload"
|
||||||
|
style="display: none;"
|
||||||
|
:disabled="connectionStatus !== 'connected'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="chat-input"
|
||||||
|
v-model="inputMessage"
|
||||||
|
@keyup.enter="sendMessage"
|
||||||
|
:placeholder="$t('chat.inputPlaceholder') || '请输入您的问题...'"
|
||||||
|
:disabled="connectionStatus !== 'connected'"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="chat-send"
|
||||||
|
@click="sendMessage"
|
||||||
|
:disabled="connectionStatus !== 'connected' || !inputMessage.trim()"
|
||||||
|
>
|
||||||
|
{{ $t("chat.send") || "发送" }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 图片预览 -->
|
||||||
|
<div v-if="showImagePreview" class="image-preview-overlay" @click="closeImagePreview">
|
||||||
|
<div class="image-preview-container">
|
||||||
|
<img :src="previewImageUrl" class="preview-image" />
|
||||||
|
<i class="el-icon-close preview-close" @click="closeImagePreview"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Client } from '@stomp/stompjs';
|
||||||
|
import { getUserid } from '../api/customerService';
|
||||||
|
export default {
|
||||||
|
name: "ChatWidget",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isChatOpen: false,
|
||||||
|
inputMessage: "",
|
||||||
|
messages: [],
|
||||||
|
unreadMessages: 0,
|
||||||
|
// 图片预览相关
|
||||||
|
showImagePreview: false,
|
||||||
|
previewImageUrl: '',
|
||||||
|
// WebSocket 相关
|
||||||
|
stompClient: null,
|
||||||
|
connectionStatus: 'disconnected', // disconnected, connecting, connected, error
|
||||||
|
userType: 0, // 0 游客 1 登录用户 2 客服
|
||||||
|
userEmail: '', // 用户标识
|
||||||
|
// 自动回复配置
|
||||||
|
autoResponses: {
|
||||||
|
hello: "您好,有什么可以帮助您的?",
|
||||||
|
你好: "您好,有什么可以帮助您的?",
|
||||||
|
hi: "您好,有什么可以帮助您的?",
|
||||||
|
挖矿: "您可以查看我们的挖矿教程,或者直接创建矿工账户开始挖矿。",
|
||||||
|
算力: "您可以在首页查看当前的矿池算力和您的个人算力。",
|
||||||
|
收益: "收益根据您的算力贡献按比例分配,详情可以查看收益计算器。",
|
||||||
|
帮助: "您可以查看我们的帮助文档,或者提交工单咨询具体问题。",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
document.addEventListener("click", this.handleClickOutside);
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
async fetchUserid(){
|
||||||
|
const res = await getUserid();
|
||||||
|
if(res &&res.code == 200){
|
||||||
|
this.roomId = res.data;
|
||||||
|
console.log(res,"及附加覅");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 初始化 WebSocket 连接
|
||||||
|
initWebSocket() {
|
||||||
|
this.determineUserType();
|
||||||
|
this.connectWebSocket();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 确定用户类型和邮箱
|
||||||
|
determineUserType() {
|
||||||
|
try {
|
||||||
|
const token = JSON.parse(localStorage.getItem('token') || '{}');
|
||||||
|
const userInfo = JSON.parse(localStorage.getItem('jurisdiction') || '{}');
|
||||||
|
const email = JSON.parse(localStorage.getItem('userEmail') || '{}');
|
||||||
|
if (token) {
|
||||||
|
if (userInfo.roleKey === 'customer_service') {
|
||||||
|
// 客服用户
|
||||||
|
this.userType = 2;
|
||||||
|
} else {
|
||||||
|
// 登录用户
|
||||||
|
this.userType = 1;
|
||||||
|
}
|
||||||
|
this.userEmail =email;
|
||||||
|
}else{//游客
|
||||||
|
this.userType = 0;
|
||||||
|
this.userEmail = `guest_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取用户信息失败:', error);
|
||||||
|
// 出错时默认为游客
|
||||||
|
this.userType = 0;
|
||||||
|
this.userEmail = `guest_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 连接 WebSocket
|
||||||
|
connectWebSocket() {
|
||||||
|
this.connectionStatus = 'connecting';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const wsUrl = `${process.env.VUE_APP_BASE_API}chat/ws`;
|
||||||
|
|
||||||
|
// 创建 STOMP 客户端
|
||||||
|
this.stompClient = new Client({
|
||||||
|
brokerURL: wsUrl,
|
||||||
|
connectHeaders: {
|
||||||
|
'email': this.userEmail,
|
||||||
|
'type': this.userType
|
||||||
|
},
|
||||||
|
debug: function(str) {
|
||||||
|
console.log('STOMP: ' + str);
|
||||||
|
},
|
||||||
|
reconnectDelay: 5000,
|
||||||
|
heartbeatIncoming: 4000,
|
||||||
|
heartbeatOutgoing: 4000
|
||||||
|
});
|
||||||
|
|
||||||
|
// 连接成功回调
|
||||||
|
this.stompClient.onConnect = (frame) => {
|
||||||
|
console.log('连接成功: ' + frame);
|
||||||
|
this.connectionStatus = 'connected';
|
||||||
|
|
||||||
|
// 订阅个人消息频道
|
||||||
|
this.stompClient.subscribe(`${process.env.VUE_APP_BASE_API}user/queue/${this.userEmail}`, this.onMessageReceived);
|
||||||
|
|
||||||
|
// 根据用户类型显示不同的欢迎消息
|
||||||
|
let welcomeMessage = '';
|
||||||
|
switch(this.userType) {
|
||||||
|
case 0:
|
||||||
|
welcomeMessage = '您当前以游客身份访问,请问有什么可以帮您?';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
welcomeMessage = '欢迎回来,请问有什么可以帮您?';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
welcomeMessage = '您已以客服身份登录系统';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.addSystemMessage(welcomeMessage);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 连接错误回调
|
||||||
|
this.stompClient.onStompError = (frame) => {
|
||||||
|
console.error('连接错误: ' + frame.headers.message);
|
||||||
|
this.connectionStatus = 'error';
|
||||||
|
this.addSystemMessage('连接客服系统失败,请稍后重试。');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启动连接
|
||||||
|
this.stompClient.activate();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化 WebSocket 失败:', error);
|
||||||
|
this.connectionStatus = 'error';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 断开 WebSocket 连接
|
||||||
|
disconnectWebSocket() {
|
||||||
|
if (this.stompClient && this.stompClient.connected) {
|
||||||
|
this.stompClient.deactivate();
|
||||||
|
this.connectionStatus = 'disconnected';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 接收消息处理
|
||||||
|
onMessageReceived(message) {
|
||||||
|
console.log('收到消息:', message.body);
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(message.body);
|
||||||
|
|
||||||
|
// 添加客服消息
|
||||||
|
this.messages.push({
|
||||||
|
type: 'system',
|
||||||
|
text: data.content,
|
||||||
|
isImage: data.type === 'image',
|
||||||
|
imageUrl: data.type === 'image' ? data.content : null,
|
||||||
|
time: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果聊天窗口没有打开,显示未读消息数
|
||||||
|
if (!this.isChatOpen) {
|
||||||
|
this.unreadMessages++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滚动到底部
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollToBottom();
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析消息失败:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 切换聊天窗口
|
||||||
|
toggleChat() {
|
||||||
|
this.isChatOpen = !this.isChatOpen;
|
||||||
|
|
||||||
|
if (this.isChatOpen) {
|
||||||
|
this.unreadMessages = 0;
|
||||||
|
|
||||||
|
// 如果未连接,则连接 WebSocket
|
||||||
|
if (this.connectionStatus === 'disconnected') {
|
||||||
|
this.initWebSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollToBottom();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
minimizeChat() {
|
||||||
|
this.isChatOpen = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
closeChat() {
|
||||||
|
this.isChatOpen = false;
|
||||||
|
this.messages = [];
|
||||||
|
this.disconnectWebSocket();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 发送消息
|
||||||
|
sendMessage() {
|
||||||
|
if (!this.inputMessage.trim() || this.connectionStatus !== 'connected') return;
|
||||||
|
|
||||||
|
const messageText = this.inputMessage.trim();
|
||||||
|
|
||||||
|
// 添加用户消息到界面
|
||||||
|
this.messages.push({
|
||||||
|
type:0,// 0 文本 1图片
|
||||||
|
text: messageText,
|
||||||
|
isImage: false,
|
||||||
|
time: new Date(),
|
||||||
|
email:"",// 接收者邮箱?
|
||||||
|
receiveUserType:2,// 接受用户类型0 游客 1 登录用户 2 客服人员
|
||||||
|
sendUserType:this.userType,// 发送者类型0 游客 1 登录用户 2 客服人员
|
||||||
|
roomId:this.roomId,// 聊天室ID
|
||||||
|
});
|
||||||
|
|
||||||
|
// 通过 WebSocket 发送消息
|
||||||
|
if (this.stompClient && this.stompClient.connected) {
|
||||||
|
this.stompClient.publish({
|
||||||
|
destination: '/send/message',
|
||||||
|
body: JSON.stringify({
|
||||||
|
content: messageText,
|
||||||
|
type: 'text'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 如果连接失败,使用自动回复
|
||||||
|
this.handleAutoResponse(messageText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空输入框
|
||||||
|
this.inputMessage = "";
|
||||||
|
|
||||||
|
// 滚动到底部
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollToBottom();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 添加系统消息
|
||||||
|
addSystemMessage(text) {
|
||||||
|
this.messages.push({
|
||||||
|
type: "system",
|
||||||
|
text: text,
|
||||||
|
isImage: false,
|
||||||
|
time: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// 滚动到底部
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollToBottom();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 自动回复 (仅在无法连接服务器时使用)
|
||||||
|
handleAutoResponse(message) {
|
||||||
|
setTimeout(() => {
|
||||||
|
let response = "抱歉,我暂时无法回答这个问题。请联系真人客服或提交工单。";
|
||||||
|
|
||||||
|
// 检查是否匹配自动回复关键词
|
||||||
|
for (const [keyword, reply] of Object.entries(this.autoResponses)) {
|
||||||
|
if (message.toLowerCase().includes(keyword.toLowerCase())) {
|
||||||
|
response = reply;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加系统回复
|
||||||
|
this.messages.push({
|
||||||
|
type: "system",
|
||||||
|
text: response,
|
||||||
|
isImage: false,
|
||||||
|
time: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.isChatOpen) {
|
||||||
|
this.unreadMessages++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollToBottom();
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollToBottom() {
|
||||||
|
if (this.$refs.chatBody) {
|
||||||
|
this.$refs.chatBody.scrollTop = this.$refs.chatBody.scrollHeight;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
formatTime(date) {
|
||||||
|
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClickOutside(event) {
|
||||||
|
if (this.isChatOpen) {
|
||||||
|
const chatElement = this.$el.querySelector('.chat-dialog');
|
||||||
|
const chatIcon = this.$el.querySelector('.chat-icon');
|
||||||
|
this.fetchUserid();
|
||||||
|
if (chatElement && !chatElement.contains(event.target) && !chatIcon.contains(event.target)) {
|
||||||
|
this.isChatOpen = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理图片上传
|
||||||
|
handleImageUpload(event) {
|
||||||
|
if (this.connectionStatus !== 'connected') return;
|
||||||
|
|
||||||
|
const file = event.target.files[0];
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
// 检查是否为图片
|
||||||
|
if (!file.type.startsWith('image/')) {
|
||||||
|
this.$message({
|
||||||
|
message: this.$t('chat.onlyImages') || '只能上传图片文件!',
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件大小 (限制为5MB)
|
||||||
|
const maxSize = 5 * 1024 * 1024;
|
||||||
|
if (file.size > maxSize) {
|
||||||
|
this.$message({
|
||||||
|
message: this.$t('chat.imageTooLarge') || '图片大小不能超过5MB!',
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => {
|
||||||
|
const imageUrl = e.target.result;
|
||||||
|
|
||||||
|
// 添加用户图片消息到界面
|
||||||
|
this.messages.push({
|
||||||
|
type:1,// 0 文本 1图片
|
||||||
|
text: "",
|
||||||
|
isImage: true,
|
||||||
|
imageUrl: imageUrl,
|
||||||
|
time: new Date(),
|
||||||
|
email:"",// 接收者邮箱?
|
||||||
|
receiveUserType:2,// 接受用户类型0 游客 1 登录用户 2 客服人员
|
||||||
|
sendUserType:this.userType,// 发送者类型0 游客 1 登录用户 2 客服人员
|
||||||
|
roomId:this.roomId,// 聊天室ID
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 通过 WebSocket 发送图片消息
|
||||||
|
if (this.stompClient && this.stompClient.connected) {
|
||||||
|
this.stompClient.publish({
|
||||||
|
destination: '/send/message',
|
||||||
|
body: JSON.stringify({
|
||||||
|
content: imageUrl,
|
||||||
|
type: 'image'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollToBottom();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
this.$refs.imageUpload.value = '';
|
||||||
|
},
|
||||||
|
|
||||||
|
// 预览图片
|
||||||
|
previewImage(imageUrl) {
|
||||||
|
this.previewImageUrl = imageUrl;
|
||||||
|
this.showImagePreview = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 关闭图片预览
|
||||||
|
closeImagePreview() {
|
||||||
|
this.showImagePreview = false;
|
||||||
|
this.previewImageUrl = '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.disconnectWebSocket();
|
||||||
|
document.removeEventListener("click", this.handleClickOutside);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.chat-widget {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 40px;
|
||||||
|
right: 60px;
|
||||||
|
z-index: 1000;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-icon {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #AC85E0;
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
background-color: #6E3EDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #6E3EDB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.unread-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: -5px;
|
||||||
|
right: -5px;
|
||||||
|
background-color: #e74c3c;
|
||||||
|
color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-dialog {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 80px;
|
||||||
|
right: 0;
|
||||||
|
width: 350px;
|
||||||
|
height: 450px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-header {
|
||||||
|
background-color: #AC85E0;
|
||||||
|
color: white;
|
||||||
|
padding: 15px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-body {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 15px;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-status {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 32px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 8px 0;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.connecting i {
|
||||||
|
color: #AC85E0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
i {
|
||||||
|
color: #e74c3c;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #e74c3c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry-button {
|
||||||
|
margin-top: 16px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
background-color: #AC85E0;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #6E3EDB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-empty {
|
||||||
|
color: #777;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
&.chat-message-user {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
|
||||||
|
.message-content {
|
||||||
|
background-color: #AC85E0;
|
||||||
|
color: white;
|
||||||
|
border-radius: 18px 18px 0 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-time {
|
||||||
|
text-align: right;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.chat-message-system {
|
||||||
|
.message-content {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 18px 18px 18px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-avatar {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
margin: 0 10px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content {
|
||||||
|
max-width: 70%;
|
||||||
|
padding: 10px 15px;
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-text {
|
||||||
|
line-height: 1.4;
|
||||||
|
font-size: 14px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-image {
|
||||||
|
img {
|
||||||
|
max-width: 200px;
|
||||||
|
max-height: 200px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.03);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-time {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-footer {
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
border-top: 1px solid #e0e0e0;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-toolbar {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-upload-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #666;
|
||||||
|
|
||||||
|
&:hover:not(.disabled) {
|
||||||
|
color: #AC85E0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input {
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 8px 15px;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&:focus:not(:disabled) {
|
||||||
|
border-color: #AC85E0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-send {
|
||||||
|
background-color: #AC85E0;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 8px 15px;
|
||||||
|
margin-left: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background-color: #6E3EDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片预览
|
||||||
|
.image-preview-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
|
z-index: 1100;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-preview-container {
|
||||||
|
position: relative;
|
||||||
|
max-width: 90%;
|
||||||
|
max-height: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 90vh;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-close {
|
||||||
|
position: absolute;
|
||||||
|
top: -40px;
|
||||||
|
right: 0;
|
||||||
|
color: white;
|
||||||
|
font-size: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动画效果
|
||||||
|
.chat-slide-enter-active, .chat-slide-leave-active {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-slide-enter, .chat-slide-leave-to {
|
||||||
|
transform: translateY(20px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动端适配
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.chat-widget {
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-dialog {
|
||||||
|
width: 300px;
|
||||||
|
height: 400px;
|
||||||
|
bottom: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-image img {
|
||||||
|
max-width: 150px;
|
||||||
|
max-height: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,32 @@
|
||||||
|
export const ChatWidget_zh = {
|
||||||
|
chat:{
|
||||||
|
|
||||||
|
title: '在线客服',
|
||||||
|
welcome: '欢迎使用在线客服,请问有什么可以帮您?',
|
||||||
|
placeholder: '请输入您的消息...',
|
||||||
|
send: '发送',
|
||||||
|
close: '关闭',
|
||||||
|
inputPlaceholder:"请输入您的问题...",
|
||||||
|
onlyImages:"只能上传图片文件!",
|
||||||
|
imageTooLarge:"图片大小不能超过5MB!",
|
||||||
|
imageReceived:"已收到您的图片,我们会尽快处理您的问题。",
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChatWidget_en = {
|
||||||
|
|
||||||
|
|
||||||
|
chat:{
|
||||||
|
title: 'Online Customer Service',
|
||||||
|
welcome: 'Welcome to the online customer service, what can I help you with?',
|
||||||
|
placeholder: 'Please enter your message...',
|
||||||
|
send: 'Send',
|
||||||
|
close: 'Close',
|
||||||
|
inputPlaceholder:"Please enter your question...",
|
||||||
|
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.",
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import {workOrder_zh,workOrder_en} from'./submitWorkOrder'
|
||||||
import {alerts_zh,alerts_en} from'./alerts'
|
import {alerts_zh,alerts_en} from'./alerts'
|
||||||
import {seo_zh,seo_en} from'./seo'
|
import {seo_zh,seo_en} from'./seo'
|
||||||
import {chooseUs_zh,chooseUs_en} from'./dataDisplay'
|
import {chooseUs_zh,chooseUs_en} from'./dataDisplay'
|
||||||
|
import {ChatWidget_zh,ChatWidget_en} from'./ChatWidget'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ export default {
|
||||||
...alerts_zh,
|
...alerts_zh,
|
||||||
...seo_zh,
|
...seo_zh,
|
||||||
...chooseUs_zh,
|
...chooseUs_zh,
|
||||||
|
...ChatWidget_zh,
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -50,7 +51,7 @@ export default {
|
||||||
...alerts_en,
|
...alerts_en,
|
||||||
...seo_en,
|
...seo_en,
|
||||||
...chooseUs_en,
|
...chooseUs_en,
|
||||||
|
...ChatWidget_en,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,22 @@ const childrenRoutes = [
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{//在线客服
|
||||||
|
path: 'customerService',
|
||||||
|
name: 'CustomerService',
|
||||||
|
component: () => import('../views/customerService/index.vue'),
|
||||||
|
meta: {title: '在线客服',
|
||||||
|
description:i18n.t(`seo.apiFile`),
|
||||||
|
allAuthority:[`all`],
|
||||||
|
// keywords: 'M2Pool 矿池,API 文档,认证 token,接口调用,API file,authentication token,Interface call'
|
||||||
|
keywords:{
|
||||||
|
en: 'API file,authentication token,Interface call',
|
||||||
|
zh: 'M2Pool 矿池,API 文档,认证 token,接口调用'
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
{//接入矿池页面
|
{//接入矿池页面
|
||||||
path: '/:lang/AccessMiningPool',
|
path: '/:lang/AccessMiningPool',
|
||||||
name: 'AccessMiningPool',
|
name: 'AccessMiningPool',
|
||||||
|
|
|
@ -160,7 +160,10 @@ window.addEventListener('offline', () => {
|
||||||
|
|
||||||
service.defaults.retry = 2;// 重试次数
|
service.defaults.retry = 2;// 重试次数
|
||||||
service.defaults.retryDelay = 2000;
|
service.defaults.retryDelay = 2000;
|
||||||
service.defaults.shouldRetry = (error) => true
|
service.defaults.shouldRetry = (error) => {
|
||||||
|
// 只有网络错误或超时错误才进行重试
|
||||||
|
return error.message === "Network Error" || error.message.includes("timeout");
|
||||||
|
};
|
||||||
|
|
||||||
localStorage.setItem('superReportError', "")
|
localStorage.setItem('superReportError', "")
|
||||||
let superReportError = localStorage.getItem('superReportError')
|
let superReportError = localStorage.getItem('superReportError')
|
||||||
|
@ -286,7 +289,6 @@ service.interceptors.response.use(res => {
|
||||||
|
|
||||||
|
|
||||||
let { message } = error;
|
let { message } = error;
|
||||||
|
|
||||||
if (message == "Network Error" || message.includes("timeout")) {
|
if (message == "Network Error" || message.includes("timeout")) {
|
||||||
if (!navigator.onLine) {
|
if (!navigator.onLine) {
|
||||||
// 断网状态,添加到重试队列
|
// 断网状态,添加到重试队列
|
||||||
|
@ -324,15 +326,29 @@ service.interceptors.response.use(res => {
|
||||||
|
|
||||||
console.log('请求已加入断网重连队列:', error.config.url);
|
console.log('请求已加入断网重连队列:', error.config.url);
|
||||||
}
|
}
|
||||||
} else if ((error.config.retry > 0 && error.config)) {
|
} else {
|
||||||
// 保留现有的重试逻辑
|
// 网络已连接,但请求失败,尝试重试
|
||||||
error.config.retry--;
|
// 确保 config 中有 __retryCount 字段
|
||||||
|
error.config.__retryCount = error.config.__retryCount || 0;
|
||||||
|
|
||||||
|
// 判断是否可以重试
|
||||||
|
if (error.config.__retryCount < service.defaults.retry && service.defaults.shouldRetry(error)) {
|
||||||
|
// 增加重试计数
|
||||||
|
error.config.__retryCount += 1;
|
||||||
|
|
||||||
|
console.log(`[请求重试] ${error.config.url} - 第 ${error.config.__retryCount} 次重试`);
|
||||||
|
|
||||||
|
// 创建新的Promise等待一段时间后重试
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve(service(error.config));
|
resolve(service(error.config));
|
||||||
}, 2000);
|
}, service.defaults.retryDelay);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 达到最大重试次数,不再重试
|
||||||
|
console.log(`[请求失败] ${error.config.url} - 已达到最大重试次数`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!superReportError) {
|
if (!superReportError) {
|
||||||
|
@ -375,63 +391,11 @@ service.interceptors.response.use(res => {
|
||||||
// 避免完全不提示,可以在控制台记录被抑制的错误
|
// 避免完全不提示,可以在控制台记录被抑制的错误
|
||||||
console.log('[错误提示] 已抑制重复错误:', message);
|
console.log('[错误提示] 已抑制重复错误:', message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// let { message } = error;
|
|
||||||
// if (message == "Network Error") {
|
|
||||||
// // message = "后端接口网络连接异常,请刷新重试";
|
|
||||||
// const now = Date.now();
|
|
||||||
// if (now - lastNetworkErrorTime > NETWORK_ERROR_THROTTLE_TIME) {
|
|
||||||
// lastNetworkErrorTime = now; // 更新最后提示时间
|
|
||||||
// Message({
|
|
||||||
// message: window.vm.$i18n.t(`home.NetworkError`),
|
|
||||||
// type: 'error',
|
|
||||||
// duration: 4 * 1000,
|
|
||||||
// showClose: true
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
// else if (message.includes("timeout")) {
|
|
||||||
// // message = "系统接口请求超时,请刷新重试";
|
|
||||||
// Message({
|
|
||||||
// message: window.vm.$i18n.t(`home.requestTimeout`),
|
|
||||||
// type: 'error',
|
|
||||||
// duration: 5 * 1000,
|
|
||||||
// showClose: true
|
|
||||||
// })
|
|
||||||
|
|
||||||
// }
|
|
||||||
// else if (message.includes("Request failed with status code")) {
|
|
||||||
// // message = "系统接口" + message.substr(message.length - 3) + "异常";
|
|
||||||
// Message({
|
|
||||||
// message: "系统接口" + message.substr(message.length - 3) + "异常",
|
|
||||||
// type: 'error',
|
|
||||||
// duration: 5 * 1000,
|
|
||||||
// showClose: true
|
|
||||||
// })
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// Message({
|
|
||||||
// message: message,
|
|
||||||
// type: 'error',
|
|
||||||
// duration: 5 * 1000,
|
|
||||||
// showClose: true
|
|
||||||
// })
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,10 +3,10 @@
|
||||||
<section v-if="$isMobile">
|
<section v-if="$isMobile">
|
||||||
|
|
||||||
<div class="imgTop">
|
<div class="imgTop">
|
||||||
<!-- <img src="../../assets/mobile/home/home.png" alt="mining" loading="lazy" /> -->
|
<img src="../../assets/mobile/home/home.png" alt="mining" loading="lazy" />
|
||||||
|
<!--
|
||||||
<img v-if="lang == 'zh'" src="../../assets/img/enx推广.png" alt="mining" loading="lazy"/>
|
<img v-if="lang == 'zh'" src="../../assets/img/enx推广.png" alt="mining" loading="lazy"/>
|
||||||
<img v-else src="../../assets/img/enx英文推广.png" alt="mining" loading="lazy"/>
|
<img v-else src="../../assets/img/enx英文推广.png" alt="mining" loading="lazy"/> -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -329,13 +329,12 @@
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<div class="content" v-else v-loading="minerChartLoading">
|
<div class="content" v-else v-loading="minerChartLoading">
|
||||||
|
|
||||||
<div class="bgBox">
|
<div class="bgBox">
|
||||||
|
<!--
|
||||||
<img v-if="lang == 'zh'" class="bgBoxImg2Img" src="../../assets/img/enx推广.png" alt="mining" loading="lazy"/>
|
<img v-if="lang == 'zh'" class="bgBoxImg2Img" src="../../assets/img/enx推广.png" alt="mining" loading="lazy"/>
|
||||||
<img v-else class="bgBoxImg2Img" src="../../assets/img/enx英文推广.png" alt="mining" loading="lazy"/>
|
<img v-else class="bgBoxImg2Img" src="../../assets/img/enx英文推广.png" alt="mining" loading="lazy"/> -->
|
||||||
|
<img class="bgImg" src="../../assets/img/home.png" alt="mining" loading="lazy"/>
|
||||||
|
|
||||||
<!-- <img class="bgBoxImg" src="../../assets/img/enx推广.png" style="width: 100%;height: 100%;" alt="mining" loading="lazy"/> -->
|
|
||||||
</div>
|
</div>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
|
@ -785,6 +784,7 @@ export default {
|
||||||
p{
|
p{
|
||||||
width: 100% ;
|
width: 100% ;
|
||||||
background: transparent ;
|
background: transparent ;
|
||||||
|
padding-left: 8px;
|
||||||
|
|
||||||
}
|
}
|
||||||
i{
|
i{
|
||||||
|
@ -1295,16 +1295,44 @@ export default {
|
||||||
@media screen and (min-width:800px) and (max-width: 1279px) {
|
@media screen and (min-width:800px) and (max-width: 1279px) {
|
||||||
.imgTop {
|
.imgTop {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
// padding-left: 10%;
|
padding-left: 20%;
|
||||||
text-align: center;
|
text-align: left;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: auto ;
|
||||||
|
height:300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#chart {
|
#chart {
|
||||||
height: 400px !important;
|
height: 400px !important;
|
||||||
}
|
}
|
||||||
|
.describeBox2{
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
padding: 8px;
|
||||||
|
margin: 0 auto;
|
||||||
|
p{
|
||||||
|
width: 100% ;
|
||||||
|
background: transparent ;
|
||||||
|
padding-left: 8px;
|
||||||
|
|
||||||
|
}
|
||||||
|
i{
|
||||||
|
color: #5721e4;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.describeTitle{
|
||||||
|
color: #5721e4;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view{
|
||||||
|
color: #5721e4;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.moveCurrencyBox {
|
.moveCurrencyBox {
|
||||||
|
@ -2046,7 +2074,7 @@ export default {
|
||||||
.bgBox {
|
.bgBox {
|
||||||
// background: gold;
|
// background: gold;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
// height: 380px;
|
height: 300px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
// background-position: 50% 28%;
|
// background-position: 50% 28%;
|
||||||
// background-size: cover;
|
// background-size: cover;
|
||||||
|
@ -2059,12 +2087,20 @@ export default {
|
||||||
// background-position: 13.2vw 0 ;
|
// background-position: 13.2vw 0 ;
|
||||||
// background-repeat: no-repeat;
|
// background-repeat: no-repeat;
|
||||||
// margin-top: 50px;
|
// margin-top: 50px;
|
||||||
margin: 30px 0px;
|
// margin: 30px 0px;
|
||||||
|
|
||||||
text-align: center;
|
text-align: left;
|
||||||
|
.bgImg{
|
||||||
|
height: 100%;
|
||||||
|
width: auto ;
|
||||||
|
position: absolute;
|
||||||
|
left: 25vw;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.bgBoxImg {
|
.bgBoxImg {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 23%;
|
left: 23%;
|
||||||
transition: all 0.3s linear;
|
transition: all 0.3s linear;
|
||||||
|
|
|
@ -69,7 +69,7 @@ export default {
|
||||||
value:"enx",
|
value:"enx",
|
||||||
label:"Entropyx(Enx)",
|
label:"Entropyx(Enx)",
|
||||||
img:`${this.$baseApi}img/enx.svg`,
|
img:`${this.$baseApi}img/enx.svg`,
|
||||||
rate:"0",
|
rate:"1%",
|
||||||
address:"",
|
address:"",
|
||||||
mode:"PPLNS+PROPDIF",
|
mode:"PPLNS+PROPDIF",
|
||||||
quota:"5000",
|
quota:"5000",
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<div class="collapseTitle">
|
<div class="collapseTitle">
|
||||||
<span ><img :src="item.img" alt="coin" loading="lazy"> {{item.label}}</span>
|
<span ><img :src="item.img" alt="coin" loading="lazy"> {{item.label}}</span>
|
||||||
<span v-if="item.value === 'enx'"> {{ $t(`course.timeLimited`) }} 0%</span>
|
<!-- <span v-if="item.value === 'enx'"> {{ $t(`course.timeLimited`) }} 0%</span> -->
|
||||||
<span v-else>{{item.rate}}</span>
|
<span >{{item.rate}}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<section class="contentBox2">
|
<section class="contentBox2">
|
||||||
|
@ -76,8 +76,8 @@
|
||||||
<li v-for="item in rateList" :key="item.value">
|
<li v-for="item in rateList" :key="item.value">
|
||||||
<span class="coin"><img :src="item.img" alt="coin" loading="lazy"> {{item.label}}</span>
|
<span class="coin"><img :src="item.img" alt="coin" loading="lazy"> {{item.label}}</span>
|
||||||
<span>{{item.address}}</span>
|
<span>{{item.address}}</span>
|
||||||
<span v-if="item.value === 'enx'"> {{ $t(`course.timeLimited`) }} 0%</span>
|
<!-- <span v-if="item.value === 'enx'"> {{ $t(`course.timeLimited`) }} 0%</span> -->
|
||||||
<span v-else>{{item.rate}}</span>
|
<span >{{item.rate}}</span>
|
||||||
<span>{{item.mode}}</span>
|
<span>{{item.mode}}</span>
|
||||||
<span>{{item.quota}}</span>
|
<span>{{item.quota}}</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,153 +1,397 @@
|
||||||
<template>
|
<template>
|
||||||
<div style="width: 1300px; height: 600px">
|
<div>
|
||||||
<div id="chart" style="width: 100%; height: 100%; min-width: 500px"></div>
|
<h1>{{ msg }}</h1>
|
||||||
|
|
||||||
|
<!-- 用户ID输入部分 -->
|
||||||
|
<div class="user-input-container">
|
||||||
|
<div class="input-group" :class="{ 'disabled': isConnected }">
|
||||||
|
<input
|
||||||
|
v-model="email"
|
||||||
|
placeholder="请输入您的用户邮箱"
|
||||||
|
:disabled="isConnected"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="targetEmail"
|
||||||
|
placeholder="请输入目标用户邮箱"
|
||||||
|
:disabled="isConnected"
|
||||||
|
@keyup.enter="!isConnected && !isConnecting && connectWebSocket()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="button-group">
|
||||||
|
<button
|
||||||
|
@click="connectWebSocket"
|
||||||
|
:disabled="isConnected || isConnecting || !email || !targetEmail"
|
||||||
|
:class="{ 'disabled': isConnected || isConnecting || !email || !targetEmail }"
|
||||||
|
>
|
||||||
|
{{ isConnecting ? '连接中...' : '连接' }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="isConnected"
|
||||||
|
@click="disconnectWebSocket"
|
||||||
|
class="disconnect-btn"
|
||||||
|
>
|
||||||
|
断开连接
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="connectionError" class="error-message">
|
||||||
|
{{ connectionError }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="isConnected">
|
||||||
|
<!-- WebSocket 聊天部分 -->
|
||||||
|
<div class="chat-container">
|
||||||
|
<div class="message-list" ref="messageList">
|
||||||
|
<div v-for="(msg, index) in receivedMessages" :key="index" class="message"
|
||||||
|
:class="{ 'error-message': msg.error }">
|
||||||
|
<div v-if="typeof msg === 'string'">{{ msg }}</div>
|
||||||
|
<div v-else>
|
||||||
|
<div class="message-header">
|
||||||
|
<span class="message-sender">{{ msg.sender || 'Unknown' }}</span>
|
||||||
|
<span class="message-time">{{ formatTime(msg.timestamp) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="message-content">{{ msg.content }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-container">
|
||||||
|
<textarea
|
||||||
|
v-model="message"
|
||||||
|
@keyup.enter="sendMessage"
|
||||||
|
placeholder="输入消息..."
|
||||||
|
rows="3"
|
||||||
|
></textarea>
|
||||||
|
<button @click="sendMessage" :disabled="!message.trim()">
|
||||||
|
发送
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import * as echarts from "echarts";
|
import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue'
|
||||||
export default {
|
import { Stomp } from '@stomp/stompjs'
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
countDownTime: 60,
|
|
||||||
timer: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
const props = defineProps({
|
||||||
let base = +new Date(1968, 9, 3);
|
msg: {
|
||||||
let oneDay = 24 * 3600 * 1000;
|
type: String,
|
||||||
let date = [];
|
required: true
|
||||||
let data = [Math.random() * 300];
|
}
|
||||||
for (let i = 1; i < 20000; i++) {
|
})
|
||||||
var now = new Date((base += oneDay));
|
|
||||||
date.push([now.getFullYear(), now.getMonth() + 1, now.getDate()].join("/"));
|
const message = ref('')
|
||||||
data.push(Math.round((Math.random() - 0.5) * 20 + data[i - 1]));
|
const receivedMessages = ref([])
|
||||||
|
const email = ref('')
|
||||||
|
const targetEmail = ref('')
|
||||||
|
const isConnected = ref(false)
|
||||||
|
const isConnecting = ref(false)
|
||||||
|
const connectionError = ref('')
|
||||||
|
const messageList = ref(null)
|
||||||
|
|
||||||
|
// 创建一个响应式的 stompClient
|
||||||
|
const stompClient = ref(null)
|
||||||
|
|
||||||
|
// 添加连接时间变量
|
||||||
|
const connectTime = ref(null)
|
||||||
|
|
||||||
|
// 自动滚动到底部
|
||||||
|
const scrollToBottom = async () => {
|
||||||
|
await nextTick()
|
||||||
|
if (messageList.value) {
|
||||||
|
messageList.value.scrollTop = messageList.value.scrollHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听消息列表变化,自动滚动
|
||||||
|
watch(receivedMessages, () => {
|
||||||
|
scrollToBottom()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 格式化时间
|
||||||
|
const formatTime = (timestamp) => {
|
||||||
|
if (!timestamp) return ''
|
||||||
|
try {
|
||||||
|
const date = new Date(timestamp)
|
||||||
|
return date.toLocaleTimeString()
|
||||||
|
} catch (e) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 连接WebSocket
|
||||||
|
const connectWebSocket = () => {
|
||||||
|
if (!email.value || !targetEmail.value) {
|
||||||
|
connectionError.value = '请输入用户邮箱和目标用户邮箱'
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加 10 个空数据在前后
|
connectionError.value = ''
|
||||||
for (let i = 0; i < 100; i++) {
|
isConnecting.value = true
|
||||||
date.unshift(null);
|
connectTime.value = new Date() // 记录连接时间
|
||||||
data.unshift(null);
|
|
||||||
}
|
try {
|
||||||
for (let i = 0; i < 100; i++) {
|
stompClient.value = Stomp.client('ws://localhost:8101/chat/ws')
|
||||||
date.push(null);
|
stompClient.value.heartbeat.outgoing = 20000
|
||||||
data.push(null);
|
stompClient.value.heartbeat.incoming = 0
|
||||||
|
|
||||||
|
const connectHeaders = {
|
||||||
|
'email': email.value,
|
||||||
|
'type': 2 //0 游客 1 登录用户 2 客服
|
||||||
}
|
}
|
||||||
|
|
||||||
var option = {
|
stompClient.value.connect(
|
||||||
tooltip: {
|
connectHeaders,
|
||||||
trigger: "axis",
|
function(frame) {
|
||||||
position: function (pt) {
|
console.log('连接成功: ' + frame)
|
||||||
return [pt[0], "10%"];
|
console.log('连接时间:', connectTime.value?.toLocaleString())
|
||||||
},
|
isConnected.value = true
|
||||||
},
|
isConnecting.value = false
|
||||||
title: {
|
|
||||||
left: "center",
|
// 添加系统消息
|
||||||
text: "Large Area Chart",
|
receivedMessages.value.push({
|
||||||
},
|
sender: 'System',
|
||||||
toolbox: {
|
content: '已连接到聊天服务器',
|
||||||
feature: {
|
timestamp: new Date().toISOString(),
|
||||||
dataZoom: {
|
system: true
|
||||||
yAxisIndex: "none",
|
})
|
||||||
},
|
|
||||||
restore: {},
|
// 订阅自己管道的消息
|
||||||
saveAsImage: {},
|
stompClient.value.subscribe(`/user/queue/${email.value}`, function(message) {
|
||||||
},
|
console.log('收到消息:', message.body)
|
||||||
},
|
try {
|
||||||
xAxis: {
|
const parsedMessage = JSON.parse(message.body)
|
||||||
type: "category",
|
receivedMessages.value.push(parsedMessage)
|
||||||
// boundaryGap: [0.5, 0.5],
|
} catch (error) {
|
||||||
data: date,
|
console.error('消息解析失败:', error)
|
||||||
},
|
receivedMessages.value.push({
|
||||||
yAxis: [
|
sender: 'System',
|
||||||
{
|
content: `消息格式错误: ${message.body}`,
|
||||||
type: "value",
|
timestamp: new Date().toISOString(),
|
||||||
boundaryGap: [0, "100%"],
|
error: true
|
||||||
axisLine: {
|
})
|
||||||
show: true, // 显示 Y 轴线条
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: "right",
|
|
||||||
type: "value",
|
|
||||||
boundaryGap: [0, "100%"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
dataZoom: [
|
|
||||||
{
|
|
||||||
type: "inside",
|
|
||||||
start: 0,
|
|
||||||
end: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: 0,
|
|
||||||
end: 10,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "Fake Data",
|
|
||||||
type: "line",
|
|
||||||
symbol: "none",
|
|
||||||
sampling: "lttb",
|
|
||||||
itemStyle: {
|
|
||||||
color: "rgb(255, 70, 131)",
|
|
||||||
},
|
|
||||||
data: data,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
this.myChart = echarts.init(document.getElementById("chart"));
|
|
||||||
this.myChart.setOption(option);
|
|
||||||
window.addEventListener(
|
|
||||||
"resize", () => {
|
|
||||||
if (this.myChart) this.myChart.resize();
|
|
||||||
}
|
}
|
||||||
);
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
function(error) {
|
||||||
//初始化图表
|
console.error('连接失败:', error)
|
||||||
inCharts() {
|
isConnected.value = false
|
||||||
if (this.myChart == null) {
|
isConnecting.value = false
|
||||||
this.myChart = echarts.init(document.getElementById("chart"));
|
connectionError.value = `连接失败: ${error.headers?.message || error.message || '未知错误'}`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化WebSocket客户端失败:', error)
|
||||||
|
isConnected.value = false
|
||||||
|
isConnecting.value = false
|
||||||
|
connectionError.value = `初始化失败: ${error.message || '未知错误'}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加断开连接方法
|
||||||
|
const disconnectWebSocket = () => {
|
||||||
|
if (stompClient.value?.connected) {
|
||||||
|
stompClient.value.disconnect(() => {
|
||||||
|
const disconnectTime = new Date()
|
||||||
|
const duration = connectTime.value ?
|
||||||
|
Math.floor((disconnectTime.getTime() - connectTime.value.getTime()) / 1000) : 0
|
||||||
|
|
||||||
|
console.log('断开连接时间:', disconnectTime.toLocaleString())
|
||||||
|
console.log(`连接持续时间: ${Math.floor(duration / 60)}分${duration % 60}秒`)
|
||||||
|
|
||||||
|
isConnected.value = false
|
||||||
|
receivedMessages.value = []
|
||||||
|
connectTime.value = null
|
||||||
|
|
||||||
|
// 添加提示
|
||||||
|
connectionError.value = '已断开连接'
|
||||||
|
setTimeout(() => {
|
||||||
|
connectionError.value = ''
|
||||||
|
}, 3000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送消息方法
|
||||||
|
const sendMessage = () => {
|
||||||
|
if (!message.value.trim()) return
|
||||||
|
|
||||||
|
if (stompClient.value?.connected) {
|
||||||
|
try {
|
||||||
|
const messageObj = {
|
||||||
|
email: targetEmail.value,
|
||||||
|
content: message.value.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.option.series[0].name = this.$t(`home.computingPower`);
|
stompClient.value.send(
|
||||||
this.option.series[1].name = this.$t(`home.currencyPrice`);
|
`/point/send/message`,
|
||||||
|
{},
|
||||||
|
JSON.stringify(messageObj)
|
||||||
|
)
|
||||||
|
|
||||||
this.myChart.setOption(this.option);
|
// 添加自己发送的消息到显示列表
|
||||||
// 回调函数,在渲染完成后执行
|
receivedMessages.value.push({
|
||||||
this.myChart.on("finished", () => {
|
sender: email.value,
|
||||||
// 在这里执行显示给用户的操作
|
content: message.value.trim(),
|
||||||
// console.log('图表渲染完成,显示给用户');
|
timestamp: new Date().toISOString(),
|
||||||
this.minerChartLoading = false;
|
isSelf: true
|
||||||
});
|
})
|
||||||
// window.addEventListener("resize", () => {
|
|
||||||
// if (this.myChart) this.myChart.resize();
|
|
||||||
// });
|
|
||||||
|
|
||||||
window.addEventListener(
|
message.value = ''
|
||||||
"resize",
|
} catch (error) {
|
||||||
throttle(() => {
|
console.error('发送消息失败:', error)
|
||||||
if (this.myChart) this.myChart.resize();
|
|
||||||
}, 200)
|
receivedMessages.value.push({
|
||||||
);
|
sender: 'System',
|
||||||
},
|
content: `发送失败: ${error.message || '未知错误'}`,
|
||||||
startCountDown() {
|
timestamp: new Date().toISOString(),
|
||||||
this.timer = setInterval(() => {
|
error: true
|
||||||
if (this.countDownTime <= 0) {
|
})
|
||||||
//当监测到countDownTime为0时,清除计数器并且移除sessionStorage,然后执行提交试卷逻辑
|
|
||||||
clearInterval(this.timer);
|
|
||||||
sessionStorage.removeItem("exam_time");
|
|
||||||
alert("提交试卷");
|
|
||||||
} else if (this.countDownTime > 0) {
|
|
||||||
//每秒让countDownTime -1秒,并设置到sessionStorage中
|
|
||||||
this.countDownTime--;
|
|
||||||
window.sessionStorage.setItem("exam_time", this.countDownTime);
|
|
||||||
}
|
}
|
||||||
}, 1000);
|
} else {
|
||||||
},
|
connectionError.value = '连接已断开,请重新连接'
|
||||||
},
|
isConnected.value = false
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件卸载时断开连接
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (stompClient.value?.connected) {
|
||||||
|
stompClient.value.disconnect()
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.read-the-docs {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-input-container {
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 20px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-list {
|
||||||
|
height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
margin: 8px 0;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 8px;
|
||||||
|
max-width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-sender {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-time {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content {
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message[class*="isSelf"] {
|
||||||
|
background-color: #dcf8c6;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
background-color: #ffebee;
|
||||||
|
color: #d32f2f;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 10px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, textarea {
|
||||||
|
flex: 1;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: inherit;
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 8px 16px;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover:not(:disabled) {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disconnect-btn {
|
||||||
|
background-color: #dc3545;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disconnect-btn:hover {
|
||||||
|
background-color: #c82333;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:disabled, textarea:disabled {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -105,9 +105,9 @@ export default {
|
||||||
console.log(res,"文件返回");
|
console.log(res,"文件返回");
|
||||||
|
|
||||||
this.ruleForm.files = res.data.data.id
|
this.ruleForm.files = res.data.data.id
|
||||||
if (this.ruleForm.files) {//成功拿到返回ID
|
// if (this.ruleForm.files) {//成功拿到返回ID
|
||||||
this.fetchSubmitWork(this.ruleForm)
|
// this.fetchSubmitWork(this.ruleForm)
|
||||||
}
|
// }
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
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.
Binary file not shown.
After Width: | Height: | Size: 716 KiB |
Binary file not shown.
After Width: | Height: | Size: 124 KiB |
|
@ -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_irzdjxdsrq8.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.d4a64849.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.454dc86a.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.b12571df.js></script><script defer src=/js/app-5c551db8.4db2eb93.js></script><script defer src=/js/app-01dc9ae1.188fe4f5.js></script><script defer src=/js/app-b4c4f6ec.025712d3.js></script><script defer src=/js/app-72600b29.5a5f9303.js></script><script defer src=/js/app-f035d474.30e8939b.js></script><script defer src=/js/app-113c6c50.96c3bebd.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/app-42f9d7e6.afc6aa48.css rel=stylesheet><link href=/css/app-01dc9ae1.825b7ca3.css rel=stylesheet><link href=/css/app-b4c4f6ec.fbcc1022.css rel=stylesheet><link href=/css/app-72600b29.4fd214e9.css rel=stylesheet><link href=/css/app-f035d474.0e6b8898.css rel=stylesheet><link href=/css/app-113c6c50.6cbc2492.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_irzdjxdsrq8.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.17cb0808.js></script><script defer src=/js/app-5c551db8.2b99b68c.js></script><script defer src=/js/app-01dc9ae1.188fe4f5.js></script><script defer src=/js/app-b4c4f6ec.bf0536f4.js></script><script defer src=/js/app-72600b29.6b68c3d1.js></script><script defer src=/js/app-f035d474.30e8939b.js></script><script defer src=/js/app-113c6c50.28d27f0c.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/app-42f9d7e6.23095695.css rel=stylesheet><link href=/css/app-01dc9ae1.825b7ca3.css rel=stylesheet><link href=/css/app-b4c4f6ec.c96edfc1.css rel=stylesheet><link href=/css/app-72600b29.83c22f01.css rel=stylesheet><link href=/css/app-f035d474.0e6b8898.css rel=stylesheet><link href=/css/app-113c6c50.af06316f.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.
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-04-18T06:25:55.062Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-04-18T06:25:55.062Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-04-18T06:25:55.062Z</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-04-22T06:17:28.553Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-04-22T06:17:28.553Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-04-22T06:17:28.553Z</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-04-18T06:25:55.043Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-04-18T06:25:55.052Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-04-18T06:25:55.052Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-04-18T06:25:55.052Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-04-18T06:25:55.052Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-04-18T06:25:55.052Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-04-18T06:25:55.052Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-04-18T06:25:55.052Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-04-18T06:25:55.052Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-04-18T06:25:55.053Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-04-18T06:25:55.053Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-04-18T06:25:55.053Z</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-04-22T06:17:28.543Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-04-22T06:17:28.543Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>
|
Binary file not shown.
Loading…
Reference in New Issue