1.1需求完成
This commit is contained in:
parent
62260e8483
commit
c6f765f858
|
@ -5,8 +5,8 @@ VUE_APP_TITLE = m2pool
|
||||||
ENV = 'development'
|
ENV = 'development'
|
||||||
|
|
||||||
#开发环境
|
#开发环境
|
||||||
VUE_APP_BASE_API = 'http://test.m2pool.com/api/'
|
VUE_APP_BASE_API = 'https://test.m2pool.com/api/'
|
||||||
# VUE_APP_BASE_API = 'http://18.183.240.108:8080/api/'
|
# VUE_APP_BASE_API = 'http://18.183.240.108:8080/api/'
|
||||||
VUE_APP_BASE_URL = 'http://test.m2pool.com/'
|
VUE_APP_BASE_URL = 'https://test.m2pool.com/'
|
||||||
# 路由懒加载
|
# 路由懒加载
|
||||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
||||||
|
|
|
@ -8,8 +8,8 @@ ENV = 'staging'
|
||||||
|
|
||||||
# 测试环境
|
# 测试环境
|
||||||
# VUE_APP_BASE_API = 'http://18.183.240.108:8080/api/'
|
# VUE_APP_BASE_API = 'http://18.183.240.108:8080/api/'
|
||||||
VUE_APP_BASE_API = 'http://test.m2pool.com/api/'
|
VUE_APP_BASE_API = 'https://test.m2pool.com/api/'
|
||||||
VUE_APP_BASE_URL = 'http://test.m2pool.com/'
|
VUE_APP_BASE_URL = 'https://test.m2pool.com/'
|
||||||
|
|
||||||
# 路由懒加载
|
# 路由懒加载
|
||||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
Binary file not shown.
|
@ -53,7 +53,7 @@
|
||||||
|
|
||||||
<router-view v-if="key !== '/zh' && key !== '/en' &&key !== '/zh/login' && key !== '/en/login' && key !== '/zh/register' && key !== '/en/register'" :key="key" />
|
<router-view v-if="key !== '/zh' && key !== '/en' &&key !== '/zh/login' && key !== '/en/login' && key !== '/zh/register' && key !== '/en/register'" :key="key" />
|
||||||
<div v-else style="color: #333;font-size: 16px;text-align: center;line-height: 100vh;">
|
<div v-else style="color: #333;font-size: 16px;text-align: center;line-height: 100vh;">
|
||||||
选择左侧导航栏查看页面
|
{{ $t("backendSystem.leftNavigation") }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</el-main>
|
</el-main>
|
||||||
|
@ -118,6 +118,9 @@ export default {
|
||||||
}
|
}
|
||||||
this.userEmail = userEmail;
|
this.userEmail = userEmail;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//网络变化
|
||||||
|
window.addEventListener("online", this.handleNetworkChange);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchSignOut() {
|
async fetchSignOut() {
|
||||||
|
@ -178,7 +181,19 @@ export default {
|
||||||
this.$message.error(this.$t("common.langChangeFailed"));
|
this.$message.error(this.$t("common.langChangeFailed"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 处理网络状态变化
|
||||||
|
handleNetworkChange() {
|
||||||
|
|
||||||
|
if (navigator.onLine) {
|
||||||
|
// === 强制重置状态,兜底 ===
|
||||||
|
location.reload(); // 重新加载当前页面
|
||||||
|
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener("online", this.handleNetworkChange);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1429,7 +1429,6 @@ export default {
|
||||||
// 加载历史消息
|
// 加载历史消息
|
||||||
async loadHistoryMessages() {
|
async loadHistoryMessages() {
|
||||||
if (this.isLoadingHistory || !this.roomId) return;
|
if (this.isLoadingHistory || !this.roomId) return;
|
||||||
|
|
||||||
this.isLoadingHistory = true;
|
this.isLoadingHistory = true;
|
||||||
try {
|
try {
|
||||||
const response = await getHistory7({
|
const response = await getHistory7({
|
||||||
|
@ -1437,41 +1436,18 @@ export default {
|
||||||
userType: this.userType,
|
userType: this.userType,
|
||||||
email: this.userEmail,
|
email: this.userEmail,
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log("📋 初始历史消息加载响应:", {
|
|
||||||
// code: response?.code,
|
|
||||||
// dataExists: !!response?.data,
|
|
||||||
// dataLength: response?.data?.length || 0,
|
|
||||||
// isArray: Array.isArray(response?.data),
|
|
||||||
// });
|
|
||||||
|
|
||||||
if (response?.code === 200 && Array.isArray(response.data)) {
|
if (response?.code === 200 && Array.isArray(response.data)) {
|
||||||
// 使用统一的格式化方法
|
|
||||||
const historyMessages = this.formatHistoryMessages(response.data);
|
const historyMessages = this.formatHistoryMessages(response.data);
|
||||||
|
|
||||||
if (historyMessages.length > 0) {
|
if (historyMessages.length > 0) {
|
||||||
// 有历史消息,按时间顺序排序
|
|
||||||
this.messages = historyMessages.sort(
|
this.messages = historyMessages.sort(
|
||||||
(a, b) => new Date(a.time) - new Date(b.time)
|
(a, b) => new Date(a.time) - new Date(b.time)
|
||||||
);
|
);
|
||||||
// console.log(
|
// 不自动弹窗,只滚动
|
||||||
// "✅ 成功加载",
|
|
||||||
// historyMessages.length,
|
|
||||||
// "条初始历史消息"
|
|
||||||
// );
|
|
||||||
|
|
||||||
// 保持对话框打开状态
|
|
||||||
this.isChatOpen = true;
|
|
||||||
this.isMinimized = false;
|
|
||||||
|
|
||||||
// 只有在初始加载历史消息时才滚动到底部(当消息列表为空时)
|
|
||||||
await this.$nextTick();
|
await this.$nextTick();
|
||||||
// 添加一个小延时确保所有内容都渲染完成
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.scrollToBottom(true); // 传入 true 表示强制滚动
|
this.scrollToBottom(true);
|
||||||
}, 100);
|
}, 100);
|
||||||
} else {
|
} else {
|
||||||
// 格式化后没有有效消息
|
|
||||||
this.messages = [
|
this.messages = [
|
||||||
{
|
{
|
||||||
type: "system",
|
type: "system",
|
||||||
|
@ -1480,10 +1456,8 @@ export default {
|
||||||
time: new Date().toISOString(),
|
time: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
// console.log("📋 初始历史消息为空(格式化后无有效消息)");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 响应无效或无数据
|
|
||||||
this.messages = [
|
this.messages = [
|
||||||
{
|
{
|
||||||
type: "system",
|
type: "system",
|
||||||
|
@ -1492,11 +1466,9 @@ export default {
|
||||||
time: new Date().toISOString(),
|
time: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
// console.log("📋 初始历史消息为空(响应无效)");
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("加载历史消息失败:", error);
|
console.error("加载历史消息失败:", error);
|
||||||
// === 简化历史消息加载失败提示 ===
|
|
||||||
this.$message.error(
|
this.$message.error(
|
||||||
this.$t("chat.loadHistoryFailed") || "加载历史消息失败"
|
this.$t("chat.loadHistoryFailed") || "加载历史消息失败"
|
||||||
);
|
);
|
||||||
|
|
|
@ -63,32 +63,28 @@ export default {
|
||||||
id:"3",
|
id:"3",
|
||||||
|
|
||||||
},
|
},
|
||||||
// {//用户算力
|
|
||||||
// path:"userComputingPower",
|
|
||||||
// label:`backendSystem.userComputingPower`,
|
|
||||||
// icon:"el-icon-finished",
|
|
||||||
// id:"4",
|
|
||||||
|
|
||||||
// },
|
|
||||||
],
|
],
|
||||||
activeIndex: "0",
|
activeIndex: "0",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted(){
|
mounted(){
|
||||||
const savedIndex = localStorage.getItem("activeIndex");
|
const lang = this.$i18n.locale;
|
||||||
if(savedIndex){
|
const currentPath = this.$route.path.replace(`/${lang}/`, '');
|
||||||
this.activeIndex = savedIndex;
|
// 优先根据当前路由匹配菜单项
|
||||||
|
const matchedMenu = this.menuList.find(item => item.path === currentPath);
|
||||||
|
if (matchedMenu) {
|
||||||
}else{
|
this.activeIndex = matchedMenu.id;
|
||||||
this.$addStorageEvent(1, "activeIndex", this.activeIndex);
|
this.$addStorageEvent(1, "activeIndex", matchedMenu.id);
|
||||||
|
} else {
|
||||||
|
// 如果localStorage有值,优先用localStorage
|
||||||
|
const savedIndex = localStorage.getItem("activeIndex");
|
||||||
|
if(savedIndex){
|
||||||
|
this.activeIndex = savedIndex;
|
||||||
|
} else {
|
||||||
|
this.$addStorageEvent(1, "activeIndex", this.activeIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
handleClick(item){
|
handleClick(item){
|
||||||
|
|
|
@ -45,7 +45,7 @@ export const ChatWidget_zh = {
|
||||||
readImage:"读取图片失败,请重试",
|
readImage:"读取图片失败,请重试",
|
||||||
processingFailed:"图片处理失败,请重试",
|
processingFailed:"图片处理失败,请重试",
|
||||||
Disconnected:"连接已断开",
|
Disconnected:"连接已断开",
|
||||||
reconnecting:"正在重连...",
|
reconnecting:"正在连接...",
|
||||||
contactList:"联系列表",
|
contactList:"联系列表",
|
||||||
search:"搜索最近联系人",
|
search:"搜索最近联系人",
|
||||||
tourist:"游客",
|
tourist:"游客",
|
||||||
|
@ -107,6 +107,7 @@ export const ChatWidget_zh = {
|
||||||
serviceAddressUnavailable:"服务地址不可用,请稍后重试",
|
serviceAddressUnavailable:"服务地址不可用,请稍后重试",
|
||||||
connectionFailedService:"无法连接到服务器,请稍后重试",
|
connectionFailedService:"无法连接到服务器,请稍后重试",
|
||||||
connectionFailedCustomer:"连接客服系统失败,请检查网络或稍后重试",
|
connectionFailedCustomer:"连接客服系统失败,请检查网络或稍后重试",
|
||||||
|
logoutSyncNotice:"检测到您已在其他窗口退出登录,当前窗口将自动跳转",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,7 +141,7 @@ export const ChatWidget_en = {
|
||||||
subscriptionFailed: "Message subscription failed",
|
subscriptionFailed: "Message subscription failed",
|
||||||
break: "Connection lost",
|
break: "Connection lost",
|
||||||
retry: "Retry in seconds",
|
retry: "Retry in seconds",
|
||||||
disconnectWaiting: "Reconnecting...",
|
disconnectWaiting: "connecting...",
|
||||||
sendFailed: "Send failed, please retry",
|
sendFailed: "Send failed, please retry",
|
||||||
noHistory: "No history",
|
noHistory: "No history",
|
||||||
historicalFailure: "Failed to load history",
|
historicalFailure: "Failed to load history",
|
||||||
|
|
|
@ -21,7 +21,6 @@ export const backendSystem_zh = {
|
||||||
deleteSuccess:"删除成功",
|
deleteSuccess:"删除成功",
|
||||||
editSuccess:"修改成功",
|
editSuccess:"修改成功",
|
||||||
addSuccess:"发布成功",
|
addSuccess:"发布成功",
|
||||||
|
|
||||||
cancel:"取 消",
|
cancel:"取 消",
|
||||||
publish:"发 布",
|
publish:"发 布",
|
||||||
logout:"退出",
|
logout:"退出",
|
||||||
|
@ -29,6 +28,61 @@ export const backendSystem_zh = {
|
||||||
dialogTitle:"新增广播内容",
|
dialogTitle:"新增广播内容",
|
||||||
pleaseInputContent:"请输入广播内容",
|
pleaseInputContent:"请输入广播内容",
|
||||||
newlineInvalid:"广播内容输入换行符无效",
|
newlineInvalid:"广播内容输入换行符无效",
|
||||||
|
onlineUserNum:"在线数量",
|
||||||
|
offlineUserNum:"离线数量",
|
||||||
|
userPower:"用户算力",
|
||||||
|
chartTitle:"用户算力及在离线状态图",
|
||||||
|
noData:"无数据",
|
||||||
|
startDate:"开始日期",
|
||||||
|
endDate:"结束日期",
|
||||||
|
to:"至",
|
||||||
|
userDetails:"用户详情",
|
||||||
|
return:"返回",
|
||||||
|
coin:"币种:",
|
||||||
|
user:"挖矿账户:",
|
||||||
|
amount:"交易金额:",
|
||||||
|
createDate:"收益分配日期",
|
||||||
|
maxHeight:"最大高度",
|
||||||
|
shouldOutDate:"实际转账日期",
|
||||||
|
address:"转账地址",
|
||||||
|
historyAddress:"历史支付地址:",
|
||||||
|
|
||||||
|
userManagementTitle:"注册用户管理",
|
||||||
|
pleaseInput:"请输入",
|
||||||
|
email:"邮箱:",
|
||||||
|
email2:"邮箱",
|
||||||
|
query:"查询",
|
||||||
|
coin2:"币种",
|
||||||
|
amount2:"最小起付金额",
|
||||||
|
status2:"用户状态",
|
||||||
|
minerUser2:"挖矿账号",
|
||||||
|
balance2:"支付地址",
|
||||||
|
active2:"是否自动提现",
|
||||||
|
normal:"正常",
|
||||||
|
delete:"删除",
|
||||||
|
yes:"是",
|
||||||
|
no:"否",
|
||||||
|
Details:"详情",
|
||||||
|
sendEmail:"发送邮件",
|
||||||
|
sendSuccess:"发送成功",
|
||||||
|
sendFail:"发送失败",
|
||||||
|
sendRemind:"确定发送邮件吗?",
|
||||||
|
recipient:"收件人",
|
||||||
|
subject:"邮件主题",
|
||||||
|
text:"邮件内容",
|
||||||
|
send:"发送",
|
||||||
|
emailRemind:"可输入多个邮箱,用逗号隔开",
|
||||||
|
|
||||||
|
pleaseInputCorrectEmail:"请输入正确的邮箱地址",
|
||||||
|
pleaseInputSubject:"请输入邮件主题",
|
||||||
|
pleaseInputText:"请输入邮件内容",
|
||||||
|
pleaseInputCorrectEmail2:"请输入正确的邮箱地址,多个邮箱用逗号分隔",
|
||||||
|
existDuplicateEmail:"存在重复邮箱,请检查",
|
||||||
|
pleaseInputQueryConditions:"请输入查询条件(挖矿账号、邮箱)",
|
||||||
|
emailContent:"邮件内容",
|
||||||
|
leftNavigation:"选择左侧导航栏查看页面",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +117,58 @@ export const backendSystem_en = {
|
||||||
dialogTitle:"Add Broadcast Content",
|
dialogTitle:"Add Broadcast Content",
|
||||||
pleaseInputContent:"Please input broadcast content",
|
pleaseInputContent:"Please input broadcast content",
|
||||||
newlineInvalid:"Invalid line break for broadcasting content input",
|
newlineInvalid:"Invalid line break for broadcasting content input",
|
||||||
|
onlineUserNum:"Online Number",
|
||||||
|
offlineUserNum:"Offline Number",
|
||||||
|
userPower:"User Power",
|
||||||
|
chartTitle:"User Power and Online/Offline Status Chart",
|
||||||
|
noData:"No Data",
|
||||||
|
startDate:"Start Date",
|
||||||
|
endDate:"End Date",
|
||||||
|
to:"To",
|
||||||
|
userDetails:"User Details",
|
||||||
|
return:"Return",
|
||||||
|
coin:"Coin:",
|
||||||
|
user:"Mining account:",
|
||||||
|
amount:"Amount:",
|
||||||
|
createDate:"Create Date",
|
||||||
|
maxHeight:"Max Height",
|
||||||
|
shouldOutDate:"Should Out Date",
|
||||||
|
address:"Address",
|
||||||
|
historyAddress:"History Payment Address:",
|
||||||
|
userManagementTitle:"User Management",
|
||||||
|
pleaseInput:"Please Input",
|
||||||
|
email:"Email:",
|
||||||
|
email2:"Email",
|
||||||
|
query:"Query",
|
||||||
|
coin2:"Coin",
|
||||||
|
amount2:"Minimum Payout Amount",
|
||||||
|
status2:"User Status",
|
||||||
|
minerUser2:"Miner User",
|
||||||
|
balance2:"Payment Address",
|
||||||
|
active2:"Automatic Withdrawal",
|
||||||
|
normal:"Normal",
|
||||||
|
delete:"Delete",
|
||||||
|
yes:"Yes",
|
||||||
|
no:"No",
|
||||||
|
Details:"Details",
|
||||||
|
sendEmail:"Send Email",
|
||||||
|
sendSuccess:"Send Success",
|
||||||
|
sendFail:"Send Fail",
|
||||||
|
sendRemind:"Are you sure you want to send an email?",
|
||||||
|
recipient:"Recipient",
|
||||||
|
subject:"Email Subject",
|
||||||
|
text:"Email Content",
|
||||||
|
send:"Send",
|
||||||
|
emailRemind:"Multiple emails can be entered, separated by commas",
|
||||||
|
pleaseInputCorrectEmail:"Please enter a valid email address",
|
||||||
|
pleaseInputSubject:"Please enter an email subject",
|
||||||
|
pleaseInputText:"Please enter an email content",
|
||||||
|
pleaseInputCorrectEmail2:"Please enter a valid email address, multiple emails separated by commas",
|
||||||
|
existDuplicateEmail:"Duplicate email exists, please check",
|
||||||
|
pleaseInputQueryConditions:"Please enter the query conditions (miner account, email)",
|
||||||
|
|
||||||
|
emailContent:"Email Content",
|
||||||
|
leftNavigation:"Select the left navigation bar to view the page",
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ Vue.use(ElementUI, {
|
||||||
});
|
});
|
||||||
Vue.prototype.$axios = axios
|
Vue.prototype.$axios = axios
|
||||||
|
|
||||||
// console.log = ()=>{} //全局关闭打印
|
console.log = ()=>{} //全局关闭打印
|
||||||
// 全局注册混入
|
// 全局注册混入
|
||||||
Vue.mixin(loadingStateMixin);//loading状态管理
|
Vue.mixin(loadingStateMixin);//loading状态管理
|
||||||
Vue.mixin(networkRecoveryMixin);//网络恢复后数据刷新
|
Vue.mixin(networkRecoveryMixin);//网络恢复后数据刷新
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
export default {
|
export default {
|
||||||
'401': '认证失败,无法访问系统资源,请重新登录',
|
// '401': '认证失败,无法访问系统资源,请重新登录',
|
||||||
'403': '当前操作没有权限',
|
'403': '当前操作没有权限',
|
||||||
'404': '访问资源不存在',
|
'404': '访问资源不存在',
|
||||||
'default': '系统未知错误,请反馈给管理员'
|
'default': '系统未知错误,请反馈给管理员'
|
||||||
|
|
|
@ -130,7 +130,7 @@ window.addEventListener('online', () => {
|
||||||
// 常见的加载状态
|
// 常见的加载状态
|
||||||
const commonLoadingProps = [
|
const commonLoadingProps = [
|
||||||
'minerChartLoading', 'reportBlockLoading', 'apiPageLoading',
|
'minerChartLoading', 'reportBlockLoading', 'apiPageLoading',
|
||||||
'MiningLoading', 'miniLoading'
|
'MiningLoading', 'miniLoading', 'bthLoading', 'editLoading'
|
||||||
];
|
];
|
||||||
|
|
||||||
commonLoadingProps.forEach(prop => {
|
commonLoadingProps.forEach(prop => {
|
||||||
|
@ -138,6 +138,15 @@ window.addEventListener('online', () => {
|
||||||
window.vm[prop] = false;
|
window.vm[prop] = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 重置所有以Loading结尾的状态
|
||||||
|
Object.keys(window.vm).forEach(key => {
|
||||||
|
if (key.endsWith('Loading')) {
|
||||||
|
window.vm[key] = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 触发网络重试完成事件
|
// 触发网络重试完成事件
|
||||||
|
@ -267,10 +276,10 @@ service.interceptors.response.use(res => {
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
window.vm.$router.push("/login")
|
window.vm.$router.push(`/${window.vm.$i18n.locale}/login`)
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
window.vm.$router.push("/")
|
window.vm.$router.push(`/${window.vm.$i18n.locale}/`)
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -308,10 +317,20 @@ service.interceptors.response.use(res => {
|
||||||
|
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
if (error.message && error.message.includes('canceled') || error.message.includes('Request aborted')) {
|
|
||||||
// 主动取消的请求,直接忽略,不提示
|
// 主动取消的请求,直接忽略,不提示
|
||||||
return Promise.reject(error);
|
if (
|
||||||
|
error.code === 'ERR_CANCELED' ||
|
||||||
|
(error.message && error.message.includes('canceled')) ||
|
||||||
|
error.message?.includes('Request aborted')
|
||||||
|
) {
|
||||||
|
// 静默处理,不提示,不冒泡
|
||||||
|
return new Promise(() => {}); // 返回pending Promise,阻止控制台报错
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 请求异常也要移除 处理Request aborted 错误
|
// 请求异常也要移除 处理Request aborted 错误
|
||||||
if (error.config) {
|
if (error.config) {
|
||||||
const requestKey = getRequestKey(error.config);
|
const requestKey = getRequestKey(error.config);
|
||||||
|
|
|
@ -39,6 +39,9 @@ export default {
|
||||||
editLoading: false,
|
editLoading: false,
|
||||||
byteCount: "",
|
byteCount: "",
|
||||||
isOverLimit: false,
|
isOverLimit: false,
|
||||||
|
total: 0,
|
||||||
|
pageSizes: [50, 100, 300],
|
||||||
|
currentPage: 1,
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -55,7 +58,6 @@ export default {
|
||||||
this.fetchList(this.listParams);
|
this.fetchList(this.listParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchList(params) {
|
async fetchList(params) {
|
||||||
|
@ -64,6 +66,7 @@ export default {
|
||||||
const res = await listBroadcast(params)
|
const res = await listBroadcast(params)
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
this.tableData = res.rows
|
this.tableData = res.rows
|
||||||
|
this.total = res.total
|
||||||
}
|
}
|
||||||
this.setLoading('broadcastLoading', false);
|
this.setLoading('broadcastLoading', false);
|
||||||
},
|
},
|
||||||
|
@ -109,6 +112,7 @@ export default {
|
||||||
handleClose() {
|
handleClose() {
|
||||||
this.dialogVisible = false;
|
this.dialogVisible = false;
|
||||||
this.addParams.content = ""
|
this.addParams.content = ""
|
||||||
|
this.setLoading('bthLoading', false);
|
||||||
},
|
},
|
||||||
sureAddBroadcast() {
|
sureAddBroadcast() {
|
||||||
|
|
||||||
|
@ -136,6 +140,7 @@ export default {
|
||||||
handleEditClose() {
|
handleEditClose() {
|
||||||
this.editDialogVisible = false;
|
this.editDialogVisible = false;
|
||||||
this.editParams.content = ""
|
this.editParams.content = ""
|
||||||
|
this.setLoading('editLoading', false);
|
||||||
},
|
},
|
||||||
handelDelete(row) {
|
handelDelete(row) {
|
||||||
this.deleteBroadcast({ id: row.id });
|
this.deleteBroadcast({ id: row.id });
|
||||||
|
@ -184,9 +189,28 @@ export default {
|
||||||
|
|
||||||
handelTime(time) {
|
handelTime(time) {
|
||||||
return `${time.split("T")[0]} ${time.split("T")[1]}`
|
return `${time.split("T")[0]} ${time.split("T")[1]}`
|
||||||
}
|
},
|
||||||
|
handleSizeChange(val) {
|
||||||
|
console.log(`每页 ${val} 条`);
|
||||||
|
this.listParams.pageSize = val
|
||||||
|
this.listParams.pageNum = 1
|
||||||
|
this.currentPage = 1
|
||||||
|
this.fetchList(this.listParams);
|
||||||
|
|
||||||
|
},
|
||||||
|
handleCurrentChange(val) {
|
||||||
|
console.log(`当前页: ${val}`);
|
||||||
|
this.listParams.pageNum = val
|
||||||
|
this.fetchList(this.listParams);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,153 +1,234 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="broadcastLoading">
|
<div v-loading="broadcastLoading">
|
||||||
|
<div class="main-title-box">
|
||||||
<div class="main-title-box">
|
<div class="main-title">{{ $t("backendSystem.publishedBroadcast") }}</div>
|
||||||
<div class="main-title">{{$t("backendSystem.publishedBroadcast")}}</div>
|
<el-button class="add-btn" @click="handelAddBroadcast"
|
||||||
<el-button class="add-btn" @click="handelAddBroadcast">{{$t("backendSystem.addBroadcast")}} <i class="iconfont icon-youjiantou1 arrow"></i></el-button>
|
>{{ $t("backendSystem.addBroadcast") }}
|
||||||
|
<i class="iconfont icon-youjiantou1 arrow"></i
|
||||||
</div>
|
></el-button>
|
||||||
|
|
||||||
<el-table
|
|
||||||
:data="tableData"
|
|
||||||
border
|
|
||||||
style="width: 100%; margin-bottom: 18px"
|
|
||||||
:header-cell-style="{ 'text-align': 'center' }"
|
|
||||||
:cell-style="{ 'text-align': 'center' }"
|
|
||||||
|
|
||||||
>
|
|
||||||
<el-table-column prop="id" label="ID" width="60" show-overflow-tooltip />
|
|
||||||
<el-table-column prop="createTime" :label="$t('backendSystem.createTime')" width="160" show-overflow-tooltip>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ handelTime(scope.row.createTime) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="content" :label="$t('backendSystem.content')" show-overflow-tooltip/>
|
|
||||||
<el-table-column prop="createUser" :label="$t('backendSystem.createUser')" width="160" show-overflow-tooltip/>
|
|
||||||
<el-table-column prop="updateTime" :label="$t('backendSystem.updateTime')" width="160" show-overflow-tooltip>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ handelTime(scope.row.updateTime) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="updateUser" :label="$t('backendSystem.updateUser')" width="160" show-overflow-tooltip/>
|
|
||||||
|
|
||||||
|
|
||||||
<el-table-column :label="$t('backendSystem.operation')" width="160" >
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
|
|
||||||
@click="handleEdit(scope.row)">{{$t("backendSystem.edit")}}</el-button>
|
|
||||||
|
|
||||||
|
|
||||||
<el-popconfirm
|
|
||||||
:confirm-button-text='$t(`work.confirm`)'
|
|
||||||
:cancel-button-text='$t(`work.cancel`)'
|
|
||||||
icon="el-icon-info"
|
|
||||||
icon-color="red"
|
|
||||||
:title="$t(`alerts.deleteRemind`)"
|
|
||||||
@confirm="handelDelete(scope.row)"
|
|
||||||
>
|
|
||||||
<el-button class="elBtn" size="mini" slot="reference">{{ $t(`personal.delete`) }}</el-button>
|
|
||||||
</el-popconfirm>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<!-- 新增广播弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
:title="$t('backendSystem.dialogTitle')"
|
|
||||||
:visible.sync="dialogVisible"
|
|
||||||
width="50%"
|
|
||||||
:before-close="handleClose"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
>
|
|
||||||
<el-form :model="addParams" >
|
|
||||||
<!-- v-if="isOverLimit" -->
|
|
||||||
<el-form-item >
|
|
||||||
<el-input resize="none" v-model="addParams.content" type="textarea" :rows="5" @input="val => handleInput(val, 'add')" />
|
|
||||||
<div style="color: #999; font-size: 12px; margin-top: 4px;display: flex;align-items: center;justify-content: space-between;">
|
|
||||||
<span v-if="isOverLimit"> {{$t("backendSystem.exceedingInput")}}</span>
|
|
||||||
<span> {{$t("backendSystem.newlineInvalid")}}</span>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="handleClose">{{$t("backendSystem.cancel")}}</el-button>
|
|
||||||
<el-button type="primary" :loading="bthLoading" @click="sureAddBroadcast">{{$t("backendSystem.publish")}}</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
<!-- 修改广播弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
:title="$t('backendSystem.editContent')"
|
|
||||||
:visible.sync="editDialogVisible"
|
|
||||||
width="50%"
|
|
||||||
:before-close="handleEditClose"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
>
|
|
||||||
<el-form :model="editParams" >
|
|
||||||
|
|
||||||
<el-form-item >
|
|
||||||
<el-input resize="none" v-model="editParams.content" type="textarea" :rows="5" @input="val => handleInput(val, 'edit')" />
|
|
||||||
<div style="color: #999; font-size: 12px; margin-top: 4px;display: flex;align-items: center;justify-content: space-between;">
|
|
||||||
<span v-if="isOverLimit"> {{$t("backendSystem.exceedingInput")}}</span>
|
|
||||||
<span> {{$t("backendSystem.newlineInvalid")}}</span>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="handleEditClose">{{$t("backendSystem.cancel")}}</el-button>
|
|
||||||
<el-button type="primary" :loading="editLoading" @click="sureEditBroadcast">{{$t("backendSystem.editBroadcast")}}</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
style="width: 100%; margin-bottom: 18px"
|
||||||
|
:header-cell-style="{ 'text-align': 'center' }"
|
||||||
|
:cell-style="{ 'text-align': 'center' }"
|
||||||
|
height="60vh"
|
||||||
|
>
|
||||||
|
<el-table-column prop="id" label="ID" width="60" show-overflow-tooltip />
|
||||||
|
<el-table-column
|
||||||
|
prop="createTime"
|
||||||
|
:label="$t('backendSystem.createTime')"
|
||||||
|
width="160"
|
||||||
|
show-overflow-tooltip
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ handelTime(scope.row.createTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="content"
|
||||||
|
:label="$t('backendSystem.content')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="createUser"
|
||||||
|
:label="$t('backendSystem.createUser')"
|
||||||
|
width="160"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="updateTime"
|
||||||
|
:label="$t('backendSystem.updateTime')"
|
||||||
|
width="160"
|
||||||
|
show-overflow-tooltip
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ handelTime(scope.row.updateTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="updateUser"
|
||||||
|
:label="$t('backendSystem.updateUser')"
|
||||||
|
width="160"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
|
|
||||||
|
<el-table-column :label="$t('backendSystem.operation')" width="160">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button size="mini" @click="handleEdit(scope.row)">{{
|
||||||
|
$t("backendSystem.edit")
|
||||||
|
}}</el-button>
|
||||||
|
|
||||||
|
<el-popconfirm
|
||||||
|
:confirm-button-text="$t(`work.confirm`)"
|
||||||
|
:cancel-button-text="$t(`work.cancel`)"
|
||||||
|
icon="el-icon-info"
|
||||||
|
icon-color="red"
|
||||||
|
:title="$t(`alerts.deleteRemind`)"
|
||||||
|
@confirm="handelDelete(scope.row)"
|
||||||
|
>
|
||||||
|
<el-button class="elBtn" size="mini" slot="reference">{{
|
||||||
|
$t(`personal.delete`)
|
||||||
|
}}</el-button>
|
||||||
|
</el-popconfirm>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24" style="display: flex; justify-content: center">
|
||||||
|
<el-pagination
|
||||||
|
style="margin: 0 auto; margin-top: 10px"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
:current-page.sync="currentPage"
|
||||||
|
:page-sizes="pageSizes"
|
||||||
|
:page-size="listParams.pageSize"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total"
|
||||||
|
>
|
||||||
|
</el-pagination>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 新增广播弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
:title="$t('backendSystem.dialogTitle')"
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
width="50%"
|
||||||
|
:before-close="handleClose"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form :model="addParams">
|
||||||
|
<!-- v-if="isOverLimit" -->
|
||||||
|
<el-form-item>
|
||||||
|
<el-input
|
||||||
|
resize="none"
|
||||||
|
v-model="addParams.content"
|
||||||
|
type="textarea"
|
||||||
|
:rows="5"
|
||||||
|
@input="(val) => handleInput(val, 'add')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span v-if="isOverLimit">
|
||||||
|
{{ $t("backendSystem.exceedingInput") }}</span
|
||||||
|
>
|
||||||
|
<span> {{ $t("backendSystem.newlineInvalid") }}</span>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleClose">{{
|
||||||
|
$t("backendSystem.cancel")
|
||||||
|
}}</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:loading="bthLoading"
|
||||||
|
@click="sureAddBroadcast"
|
||||||
|
>{{ $t("backendSystem.publish") }}</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
<!-- 修改广播弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
:title="$t('backendSystem.editContent')"
|
||||||
|
:visible.sync="editDialogVisible"
|
||||||
|
width="50%"
|
||||||
|
:before-close="handleEditClose"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form :model="editParams">
|
||||||
|
<el-form-item>
|
||||||
|
<el-input
|
||||||
|
resize="none"
|
||||||
|
v-model="editParams.content"
|
||||||
|
type="textarea"
|
||||||
|
:rows="5"
|
||||||
|
@input="(val) => handleInput(val, 'edit')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span v-if="isOverLimit">
|
||||||
|
{{ $t("backendSystem.exceedingInput") }}</span
|
||||||
|
>
|
||||||
|
<span> {{ $t("backendSystem.newlineInvalid") }}</span>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleEditClose">{{
|
||||||
|
$t("backendSystem.cancel")
|
||||||
|
}}</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:loading="editLoading"
|
||||||
|
@click="sureEditBroadcast"
|
||||||
|
>{{ $t("backendSystem.editBroadcast") }}</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Index from './index'
|
import Index from "./index";
|
||||||
export default {
|
export default {
|
||||||
mixins:[Index],
|
mixins: [Index],
|
||||||
|
};
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.main-title-box{
|
.main-title-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
.add-btn{
|
.add-btn {
|
||||||
background: #661FFB;
|
background: #661ffb;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border:none;
|
border: none;
|
||||||
margin-left: 28px;
|
margin-left: 28px;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
.arrow{
|
.arrow {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.add-btn:hover{
|
.add-btn:hover {
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.main-title{
|
.main-title {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.elBtn{
|
.elBtn {
|
||||||
background: #e60751;
|
background: #e60751;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border:none;
|
border: none;
|
||||||
margin-left: 18px;
|
margin-left: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -433,7 +433,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
async created() {
|
created() {
|
||||||
try {
|
try {
|
||||||
let userEmail = localStorage.getItem("userEmail");
|
let userEmail = localStorage.getItem("userEmail");
|
||||||
this.userEmail = JSON.parse(userEmail);
|
this.userEmail = JSON.parse(userEmail);
|
||||||
|
@ -443,11 +443,11 @@ export default {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取聊天室列表
|
// 获取聊天室列表
|
||||||
await this.fetchRoomList();
|
this.fetchRoomList();
|
||||||
// 在组件创建时加载手动创建的聊天室
|
// 在组件创建时加载手动创建的聊天室
|
||||||
this.loadManualCreatedRooms();
|
this.loadManualCreatedRooms();
|
||||||
|
|
||||||
console.log(this.userEmail, "初始化的时候");
|
console.log("mounted userEmail=", userEmail, "parsed=", this.userEmail);
|
||||||
// 初始化 WebSocket 连接
|
// 初始化 WebSocket 连接
|
||||||
this.initWebSocket();
|
this.initWebSocket();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -455,6 +455,8 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
|
||||||
|
|
||||||
// 获取聊天室列表
|
// 获取聊天室列表
|
||||||
await this.fetchRoomList();
|
await this.fetchRoomList();
|
||||||
|
|
||||||
|
@ -577,6 +579,9 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("走这里了嘛 家电节爱哦都觉得久啊是哦大点击");
|
||||||
|
|
||||||
|
|
||||||
// 防止重复初始化
|
// 防止重复初始化
|
||||||
if (this.stompClient && this.stompClient.state !== "DISCONNECTED") {
|
if (this.stompClient && this.stompClient.state !== "DISCONNECTED") {
|
||||||
console.log("WebSocket正在连接中,跳过初始化");
|
console.log("WebSocket正在连接中,跳过初始化");
|
||||||
|
@ -588,15 +593,9 @@ export default {
|
||||||
if (this.stompClient) {
|
if (this.stompClient) {
|
||||||
this.forceDisconnectAll();
|
this.forceDisconnectAll();
|
||||||
}
|
}
|
||||||
let apiUrl = process.env.VUE_APP_BASE_API;
|
|
||||||
let baseUrl=""
|
console.log("开始初始化WebSocket连接...");
|
||||||
// 将 https 替换为 wss
|
const baseUrl = process.env.VUE_APP_BASE_API.replace("https", "wss");
|
||||||
if (apiUrl.startsWith("https://")) {
|
|
||||||
baseUrl= apiUrl.replace("https://", "wss://");
|
|
||||||
}
|
|
||||||
if (apiUrl.startsWith("http://")) {
|
|
||||||
baseUrl=apiUrl.replace("http://", "ws://");
|
|
||||||
}
|
|
||||||
const wsUrl = `${baseUrl}chat/ws`;
|
const wsUrl = `${baseUrl}chat/ws`;
|
||||||
this.stompClient = Stomp.client(wsUrl);
|
this.stompClient = Stomp.client(wsUrl);
|
||||||
|
|
||||||
|
@ -650,11 +649,12 @@ export default {
|
||||||
this.subscribeToMessages();
|
this.subscribeToMessages();
|
||||||
this.updateLastActivityTime();
|
this.updateLastActivityTime();
|
||||||
|
|
||||||
// === 启动心跳检测 ===
|
// === 暂时禁用心跳和连接检查,避免误判 ===
|
||||||
this.startHeartbeat();
|
// this.startHeartbeat();
|
||||||
|
// this.startConnectionCheck();
|
||||||
|
|
||||||
// === 启动连接状态检查 ===
|
// 只依赖 STOMP 内置心跳和订阅成功状态
|
||||||
this.startConnectionCheck();
|
console.log("✅ 连接成功,只使用 STOMP 内置心跳机制");
|
||||||
|
|
||||||
// === 注意:不在这里启动验证,而是在订阅成功后 ===
|
// === 注意:不在这里启动验证,而是在订阅成功后 ===
|
||||||
console.log("⚡ 客服连接成功,等待订阅完成后验证");
|
console.log("⚡ 客服连接成功,等待订阅完成后验证");
|
||||||
|
@ -715,11 +715,10 @@ export default {
|
||||||
console.log("📢 客服订阅成功,立即标记连接已验证");
|
console.log("📢 客服订阅成功,立即标记连接已验证");
|
||||||
this.markConnectionVerified();
|
this.markConnectionVerified();
|
||||||
|
|
||||||
// 确保连接状态正确
|
// 强制确保连接状态正确
|
||||||
if (this.connectionStatus !== "connected") {
|
this.isWebSocketConnected = true;
|
||||||
console.log("📡 修正客服连接状态为connected");
|
this.connectionStatus = "connected";
|
||||||
this.connectionStatus = "connected";
|
console.log("✅ 强制设置连接状态为已连接");
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
console.error("❌ 客服订阅失败,返回空subscription");
|
console.error("❌ 客服订阅失败,返回空subscription");
|
||||||
// 如果订阅失败,启动验证机制等待超时重连
|
// 如果订阅失败,启动验证机制等待超时重连
|
||||||
|
@ -1735,6 +1734,10 @@ export default {
|
||||||
this.updateLastActivityTime(); // 收到消息也是一种活动
|
this.updateLastActivityTime(); // 收到消息也是一种活动
|
||||||
this.lastHeartbeatTime = Date.now(); // 更新心跳时间
|
this.lastHeartbeatTime = Date.now(); // 更新心跳时间
|
||||||
|
|
||||||
|
// 强制确保连接状态正确(收到消息说明连接肯定是好的)
|
||||||
|
this.isWebSocketConnected = true;
|
||||||
|
this.connectionStatus = "connected";
|
||||||
|
|
||||||
const msg = JSON.parse(message.body);
|
const msg = JSON.parse(message.body);
|
||||||
console.log("客服收到的消息", msg);
|
console.log("客服收到的消息", msg);
|
||||||
|
|
||||||
|
@ -3665,14 +3668,45 @@ export default {
|
||||||
localStorage.setItem(key, String(count));
|
localStorage.setItem(key, String(count));
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 监听storage事件,实现多窗口未读同步
|
* 监听storage事件,实现多窗口未读同步和登录状态同步
|
||||||
*/
|
*/
|
||||||
handleStorageChange(e) {
|
handleStorageChange(e) {
|
||||||
|
// 监听未读消息同步
|
||||||
if (e.key && e.key.startsWith("cs_unread_")) {
|
if (e.key && e.key.startsWith("cs_unread_")) {
|
||||||
const roomId = e.key.replace("cs_unread_", "");
|
const roomId = e.key.replace("cs_unread_", "");
|
||||||
const count = parseInt(e.newValue, 10) || 0;
|
const count = parseInt(e.newValue, 10) || 0;
|
||||||
const contact = this.contacts.find((c) => c.roomId == roomId);
|
const contact = this.contacts.find((c) => c.roomId == roomId);
|
||||||
if (contact) contact.unread = count;
|
if (contact) contact.unread = count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听登录状态同步 - 当userEmail被清除时表示用户已退出登录
|
||||||
|
if (e.key === "userEmail" && e.oldValue && (!e.newValue || e.newValue === "null")) {
|
||||||
|
this.handleLogoutSync();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理多窗口登录状态同步
|
||||||
|
*/
|
||||||
|
handleLogoutSync() {
|
||||||
|
try {
|
||||||
|
// 断开WebSocket连接
|
||||||
|
this.forceDisconnectAll();
|
||||||
|
|
||||||
|
// 清除本地数据
|
||||||
|
this.userEmail = "";
|
||||||
|
this.currentContactId = null;
|
||||||
|
this.contacts = [];
|
||||||
|
this.messages = {};
|
||||||
|
this.inputMessage = "";
|
||||||
|
this.isWebSocketConnected = false;
|
||||||
|
this.connectionStatus = "disconnected";
|
||||||
|
|
||||||
|
// 跳转到首页
|
||||||
|
this.$router.replace("/");
|
||||||
|
} catch (error) {
|
||||||
|
this.$router.replace("/");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -918,7 +918,7 @@ export default {
|
||||||
});
|
});
|
||||||
// this.getBroadcastList({pageNum:1,pageSize:100})
|
// this.getBroadcastList({pageNum:1,pageSize:100})
|
||||||
|
|
||||||
this.getBroadcastList()
|
this.getBroadcastList({lang:this.$i18n.locale})
|
||||||
this.startScroll();
|
this.startScroll();
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
@ -1732,6 +1732,10 @@ scrollRight() {
|
||||||
if (this.broadcastList.length <= 1) return;
|
if (this.broadcastList.length <= 1) return;
|
||||||
this.scrollTimer = setInterval(this.nextScroll, 3000);
|
this.scrollTimer = setInterval(this.nextScroll, 3000);
|
||||||
},
|
},
|
||||||
|
stopScroll() {
|
||||||
|
if (this.scrollTimer) clearInterval(this.scrollTimer);
|
||||||
|
this.scrollTimer = null;
|
||||||
|
},
|
||||||
nextScroll() {
|
nextScroll() {
|
||||||
if (this.broadcastList.length <= 1) return;
|
if (this.broadcastList.length <= 1) return;
|
||||||
this.isTransition = true;
|
this.isTransition = true;
|
||||||
|
|
|
@ -421,7 +421,8 @@
|
||||||
<div class="describe-row">
|
<div class="describe-row">
|
||||||
|
|
||||||
<div class="broadcast-scroll-wrap">
|
<div class="broadcast-scroll-wrap">
|
||||||
<div class="broadcast-scroll-list" :style="scrollStyle">
|
<div class="broadcast-scroll-list" @mouseenter="stopScroll"
|
||||||
|
@mouseleave="startScroll" :style="scrollStyle">
|
||||||
<div
|
<div
|
||||||
v-for="item in broadcastList"
|
v-for="item in broadcastList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
|
@ -430,7 +431,7 @@
|
||||||
|
|
||||||
<i class="iconfont icon-tishishuoming"></i>
|
<i class="iconfont icon-tishishuoming"></i>
|
||||||
<span class="describeTitle">{{ $t(`home.describeTitle`) }}</span>
|
<span class="describeTitle">{{ $t(`home.describeTitle`) }}</span>
|
||||||
<span> {{ item.content }}</span>
|
<span :title="item.content"> {{ item.content }}</span>
|
||||||
<span
|
<span
|
||||||
class="view"
|
class="view"
|
||||||
v-show="item.id == 'b1'"
|
v-show="item.id == 'b1'"
|
||||||
|
|
|
@ -270,6 +270,16 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
'$route'(to) {
|
||||||
|
// 路由变化时自动同步语言和radio
|
||||||
|
const match = to.path.match(/^\/(zh|en)(\/|$)/);
|
||||||
|
if (match) {
|
||||||
|
this.radio = match[1];
|
||||||
|
this.lang = match[1];
|
||||||
|
this.$i18n.locale = match[1];
|
||||||
|
localStorage.setItem("lang", match[1]);
|
||||||
|
}
|
||||||
|
},
|
||||||
"$i18n.locale": function () {
|
"$i18n.locale": function () {
|
||||||
this.translate();
|
this.translate();
|
||||||
},
|
},
|
||||||
|
@ -290,10 +300,29 @@ export default {
|
||||||
// }
|
// }
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.lang = this.$i18n.locale; // 初始化语言值
|
// this.lang = this.$i18n.locale; // 初始化语言值
|
||||||
this.radio = localStorage.getItem("lang")
|
// this.radio = localStorage.getItem("lang")
|
||||||
? localStorage.getItem("lang")
|
// ? localStorage.getItem("lang")
|
||||||
: "en";
|
// : "en";
|
||||||
|
|
||||||
|
// 获取当前路由路径
|
||||||
|
const path = this.$route.path;
|
||||||
|
// 匹配 /zh/ 或 /en/ 作为语言前缀
|
||||||
|
const match = path.match(/^\/(zh|en)(\/|$)/);
|
||||||
|
if (match) {
|
||||||
|
this.radio = match[1];
|
||||||
|
this.lang = match[1];
|
||||||
|
this.$i18n.locale = match[1];
|
||||||
|
localStorage.setItem("lang", match[1]);
|
||||||
|
} else {
|
||||||
|
// fallback 到 localStorage 或 "en"
|
||||||
|
this.radio = localStorage.getItem("lang") || "en";
|
||||||
|
this.lang = this.radio;
|
||||||
|
this.$i18n.locale = this.radio;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
translate() {
|
translate() {
|
||||||
|
|
|
@ -333,15 +333,44 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
'$route'(to) {
|
||||||
|
// 路由变化时自动同步语言和radio
|
||||||
|
const match = to.path.match(/^\/(zh|en)(\/|$)/);
|
||||||
|
if (match) {
|
||||||
|
this.radio = match[1];
|
||||||
|
this.lang = match[1];
|
||||||
|
this.$i18n.locale = match[1];
|
||||||
|
localStorage.setItem("lang", match[1]);
|
||||||
|
}
|
||||||
|
},
|
||||||
"$i18n.locale": function () {
|
"$i18n.locale": function () {
|
||||||
this.translate();
|
this.translate();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.lang = this.$i18n.locale;
|
// this.lang = this.$i18n.locale;
|
||||||
this.radio = localStorage.getItem("lang")
|
// this.radio = localStorage.getItem("lang")
|
||||||
? localStorage.getItem("lang")
|
// ? localStorage.getItem("lang")
|
||||||
: "en";
|
// : "en";
|
||||||
|
|
||||||
|
// 获取当前路由路径
|
||||||
|
const path = this.$route.path;
|
||||||
|
// 匹配 /zh/ 或 /en/ 作为语言前缀
|
||||||
|
const match = path.match(/^\/(zh|en)(\/|$)/);
|
||||||
|
if (match) {
|
||||||
|
this.radio = match[1];
|
||||||
|
this.lang = match[1];
|
||||||
|
this.$i18n.locale = match[1];
|
||||||
|
localStorage.setItem("lang", match[1]);
|
||||||
|
} else {
|
||||||
|
// fallback 到 localStorage 或 "en"
|
||||||
|
this.radio = localStorage.getItem("lang") || "en";
|
||||||
|
this.lang = this.radio;
|
||||||
|
this.$i18n.locale = this.radio;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (const key in this.registerForm) {
|
for (const key in this.registerForm) {
|
||||||
this.registerForm[key] = "";
|
this.registerForm[key] = "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { getUserDetails,getUserLineChart,getUserOnlineStatus } from '../../api/userManagement'
|
import { getUserDetails,getUserLineChart,getUserOnlineStatus } from '../../api/userManagement'
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
import { Debounce, throttle } from "../../utils/publicMethods";
|
||||||
export default {
|
export default {
|
||||||
name: 'UserDetails',
|
name: 'UserDetails',
|
||||||
data() {
|
data() {
|
||||||
|
@ -34,30 +35,341 @@ export default {
|
||||||
userDetailsParams:{
|
userDetailsParams:{
|
||||||
coin: '',
|
coin: '',
|
||||||
minerUser: '',
|
minerUser: '',
|
||||||
|
startDate:"",
|
||||||
|
endDate:"",
|
||||||
|
|
||||||
},
|
},
|
||||||
labelPosition: 'top',
|
labelPosition: 'top',
|
||||||
noDataTip: false,
|
noDataTip: false,
|
||||||
lineChartParams:{
|
lineChartParams:{
|
||||||
user: '',
|
minerUser: '',
|
||||||
endDate:"",
|
endDate:"",
|
||||||
startDate:"",
|
startDate:"",
|
||||||
coin:"",
|
coin:"",
|
||||||
|
|
||||||
},
|
},
|
||||||
onlineStatusParams:{
|
onlineStatusParams:{
|
||||||
user: '',
|
minerUser: '',
|
||||||
coin: '',
|
coin: '',
|
||||||
datePoint:"",
|
endDate:"",
|
||||||
}
|
startDate:"",
|
||||||
|
},
|
||||||
|
onlineStatusData:[
|
||||||
|
|
||||||
|
{
|
||||||
|
"date":"2024-11-28T11:00:00",
|
||||||
|
"offlineNum": 148,
|
||||||
|
"onlineNum": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date":"2025-06-27 17:00:00",
|
||||||
|
"offlineNum": 110,
|
||||||
|
"onlineNum": 156
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date":"2025-06-27 17:30:00",
|
||||||
|
"offlineNum": 90,
|
||||||
|
"onlineNum": 152
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date":"2025-06-27 18:00:00",
|
||||||
|
"offlineNum": 70,
|
||||||
|
"onlineNum": 152
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date":"2025-06-27 18:00:00",
|
||||||
|
"offlineNum": 70,
|
||||||
|
"onlineNum": 152
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date":"2025-06-27 18:00:00",
|
||||||
|
"offlineNum": 70,
|
||||||
|
"onlineNum": 152
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date":"2025-06-27 18:00:00",
|
||||||
|
"offlineNum": 70,
|
||||||
|
"onlineNum": 152
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lineChatTimes:[],
|
||||||
|
option: {
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
//解决tooltip显示不全问题1
|
||||||
|
confine: true,
|
||||||
|
|
||||||
|
// formatter: function (params) {
|
||||||
|
// var res
|
||||||
|
// res = params[0].axisValueLabel;
|
||||||
|
|
||||||
|
|
||||||
|
// for (let i = 0; i <= params.length - 1; i++) {
|
||||||
|
|
||||||
|
// if (params[i].seriesName == "Currency Price" || params[i].seriesName == "币价") {
|
||||||
|
// res += `</br>${params[i].marker} ${params[i].seriesName}      <span style="font-weight: bold">${params[i].value} USD</span>`
|
||||||
|
// } else {
|
||||||
|
// res += `</br>${params[i].marker} ${params[i].seriesName}      <span style="font-weight: bold">${params[i].value}</span>`
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// return res;
|
||||||
|
// },
|
||||||
|
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
right: "8%",
|
||||||
|
|
||||||
|
},
|
||||||
|
// grid: {//解决Y轴显示不全
|
||||||
|
// left: "10%",//10%
|
||||||
|
// containLabel: true
|
||||||
|
// },
|
||||||
|
grid: {
|
||||||
|
left: "8%",
|
||||||
|
right: "8%",
|
||||||
|
top: "10%",
|
||||||
|
bottom: "15%", // 增加底部空间,为旋转的X轴标签和滑动条留出空间
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
xAxis: {
|
||||||
|
// type: "time",
|
||||||
|
boundaryGap: true, // 让柱子不超出X轴
|
||||||
|
axisLabel: {
|
||||||
|
interval: 'auto', // 自动间隔显示标签,避免重叠
|
||||||
|
rotate: 45, // 旋转45度,避免标签重叠
|
||||||
|
formatter: function(value) {
|
||||||
|
// 格式化显示,只显示月-日 时:分
|
||||||
|
if (value.includes(' ')) {
|
||||||
|
const [date, time] = value.split(' ');
|
||||||
|
const [year, month, day] = date.split('-');
|
||||||
|
const [hour, minute] = time.split(':');
|
||||||
|
return `${month}-${day} ${hour}:${minute}`;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// axisTick: {
|
||||||
|
// //去除刻度
|
||||||
|
// show: false,
|
||||||
|
// },
|
||||||
|
// axisLine: {
|
||||||
|
// //去除轴线
|
||||||
|
// show: false,
|
||||||
|
// },
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
// position: "left",
|
||||||
|
type: "value",
|
||||||
|
name: "GH/s",
|
||||||
|
nameTextStyle: {
|
||||||
|
|
||||||
|
padding: [0, 0, 0, -40],
|
||||||
|
},
|
||||||
|
// min: `dataMin`,
|
||||||
|
// max: `dataMax`,
|
||||||
|
axisLabel: {
|
||||||
|
formatter: function (value) {
|
||||||
|
// let data
|
||||||
|
// if (value > 10000000) {
|
||||||
|
// data = `${(value / 10000000)} KW`
|
||||||
|
// } else if (value > 1000000) {
|
||||||
|
// data = `${(value / 1000000)} M`
|
||||||
|
// } else if (value / 10000) {
|
||||||
|
// data = `${(value / 10000)} W`
|
||||||
|
// }
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
position: "right",
|
||||||
|
// type: "log",
|
||||||
|
// splitNumber: "5",
|
||||||
|
show: true,
|
||||||
|
// min: 0,
|
||||||
|
// max: this.maxValue,
|
||||||
|
splitLine: {//不显示右侧Y轴横线
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
// name: "",
|
||||||
|
nameTextStyle: {
|
||||||
|
|
||||||
|
padding: [0, 0, 0, 40],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
type: "inside",
|
||||||
|
start: 50, // 默认显示后30%的数据,避免图表过于拥挤
|
||||||
|
end: 100,
|
||||||
|
maxSpan: 100,
|
||||||
|
minSpan: 2, // 最小显示5%的数据
|
||||||
|
animation: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "inside",
|
||||||
|
start: 50,
|
||||||
|
end: 100,
|
||||||
|
height: 20, // 滑动条高度
|
||||||
|
bottom: 0, // 滑动条位置
|
||||||
|
showDetail: false, // 不显示详细数值
|
||||||
|
},
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
|
||||||
|
{//在线数量
|
||||||
|
name: "Number of users online",
|
||||||
|
type: "bar",
|
||||||
|
data: [],
|
||||||
|
yAxisIndex: 1,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#239342', // 这里设置柱子的主色为绿色
|
||||||
|
|
||||||
|
},
|
||||||
|
barWidth: '40%', // 使用百分比宽度,保持适当的柱子宽度
|
||||||
|
barGap: '10%', // 同类型柱子间的间隔
|
||||||
|
barCategoryGap: '20%', // 类目间的间隔
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Number of offline users",
|
||||||
|
type: "bar",
|
||||||
|
// smooth: false, //线条是否圆滑
|
||||||
|
// symbol: "circle",
|
||||||
|
// symbolSize: 5,
|
||||||
|
// showSymbol: false,
|
||||||
|
itemStyle: {
|
||||||
|
color: "#FE2E74",
|
||||||
|
borderColor: "rgba(221,220,107,0.1)",
|
||||||
|
|
||||||
|
},
|
||||||
|
barWidth: '40%', // 使用百分比宽度,保持适当的柱子宽度
|
||||||
|
barGap: '10%', // 同类型柱子间的间隔
|
||||||
|
barCategoryGap: '20%', // 类目间的间隔
|
||||||
|
|
||||||
|
data: [],
|
||||||
|
yAxisIndex: 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "User computing power",
|
||||||
|
type: "line",
|
||||||
|
smooth: false, //线条是否圆滑
|
||||||
|
symbol: "circle",
|
||||||
|
symbolSize: 5,
|
||||||
|
showSymbol: false,
|
||||||
|
itemStyle: {
|
||||||
|
color: "#5721E4",
|
||||||
|
borderColor: "rgba(221,220,107,0.1)",
|
||||||
|
borderWidth: 12,
|
||||||
|
},
|
||||||
|
lineStyle: {
|
||||||
|
//线条样式
|
||||||
|
color: "#5721E4",
|
||||||
|
width: "2",
|
||||||
|
},
|
||||||
|
// areaStyle: {
|
||||||
|
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
// {
|
||||||
|
// offset: 0,
|
||||||
|
// color: 'rgb(210,195,234)'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// offset: 1,
|
||||||
|
// color: 'rgb(255, 255, 255)'
|
||||||
|
// }
|
||||||
|
// ])
|
||||||
|
// },
|
||||||
|
zlevel: 1, z: 1,
|
||||||
|
data: [],
|
||||||
|
yAxisIndex: 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
],
|
||||||
|
},
|
||||||
|
lineChartLoading:false,
|
||||||
|
lineChartData:[
|
||||||
|
|
||||||
|
{
|
||||||
|
"minerUser": "miner",
|
||||||
|
"pv": "8.00080",
|
||||||
|
"date": "2024-11-28T11:00:00",
|
||||||
|
"unit":"GH/s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minerUser": "miner",
|
||||||
|
"pv": "6.00060",
|
||||||
|
"date": "2024-11-28T11:30:00",
|
||||||
|
"unit":"GH/s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minerUser": "miner",
|
||||||
|
"pv": "0.05000",
|
||||||
|
"date": "2024-11-28T12:00:00",
|
||||||
|
"unit":"GH/s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minerUser": "miner",
|
||||||
|
"pv": "2.0000",
|
||||||
|
"date": "2024-11-28T12:30:00",
|
||||||
|
"unit":"GH/s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minerUser": "miner",
|
||||||
|
"pv": "0.3000",
|
||||||
|
"date": "2024-11-28T13:00:00",
|
||||||
|
"unit":"GH/s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minerUser": "miner",
|
||||||
|
"pv": "0.9000",
|
||||||
|
"date": "2024-11-28T13:30:00",
|
||||||
|
"unit":"GH/s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minerUser": "miner",
|
||||||
|
"pv": "15.0000",
|
||||||
|
"date": "2024-11-28T14:00:00",
|
||||||
|
"unit":"GH/s"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
],
|
||||||
|
chartShow:true,
|
||||||
|
tableData:[],
|
||||||
|
historyBalance:[],
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
console.log('userDetails mounted', this.$route.path, this.$route.query)
|
let token
|
||||||
|
try{
|
||||||
|
token =JSON.parse(localStorage.getItem('token'))
|
||||||
|
}catch(e){
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
if (!token) {
|
||||||
|
this.$router.push({ path: `/${lang}/login` });
|
||||||
|
|
||||||
|
}
|
||||||
const params= this.$route.query || JSON.parse(localStorage.getItem("userDetailsParams"));
|
const params= this.$route.query || JSON.parse(localStorage.getItem("userDetailsParams"));
|
||||||
this.lineChartParams.user=params.user
|
this.lineChartParams.minerUser=params.minerUser
|
||||||
this.lineChartParams.coin=params.coin
|
this.lineChartParams.coin=params.coin
|
||||||
this.onlineStatusParams.user=params.user
|
this.onlineStatusParams.minerUser=params.minerUser
|
||||||
this.onlineStatusParams.coin=params.coin
|
this.onlineStatusParams.coin=params.coin
|
||||||
this.userDetailsParams.coin=params.coin
|
this.userDetailsParams.coin=params.coin
|
||||||
this.userDetailsParams.minerUser=params.minerUser
|
this.userDetailsParams.minerUser=params.minerUser
|
||||||
|
@ -66,42 +378,132 @@ export default {
|
||||||
localStorage.setItem("userDetailsParams", JSON.stringify(params));
|
localStorage.setItem("userDetailsParams", JSON.stringify(params));
|
||||||
|
|
||||||
this.fetchUserDetails(this.userDetailsParams);
|
this.fetchUserDetails(this.userDetailsParams);
|
||||||
this.fetchUserLineChart(this.lineChartParams);
|
// 等待两个图表相关接口都完成后再调用inCharts
|
||||||
this.fetchUserOnlineStatus(this.onlineStatusParams);
|
this.fetchChartData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
//初始化图表
|
||||||
|
inCharts() {
|
||||||
|
if (this.myChart == null) {
|
||||||
|
this.myChart = echarts.init(document.getElementById("lineChart"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.option.series[0].name = this.$t(`backendSystem.onlineUserNum`)
|
||||||
|
this.option.series[1].name = this.$t(`backendSystem.offlineUserNum`)
|
||||||
|
this.option.series[2].name = this.$t(`backendSystem.userPower`)
|
||||||
|
|
||||||
|
this.myChart.setOption(this.option);
|
||||||
|
// 回调函数,在渲染完成后执行
|
||||||
|
this.myChart.on('finished', () => {
|
||||||
|
// 图表渲染完成
|
||||||
|
console.log('图表渲染完成');
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('resize', throttle(() => {
|
||||||
|
if (this.myChart) this.myChart.resize();
|
||||||
|
}, 200));
|
||||||
|
},
|
||||||
async fetchUserDetails(params) {
|
async fetchUserDetails(params) {
|
||||||
this.userDetailsLoading = true
|
this.setLoading('userDetailsLoading', true);
|
||||||
// 这里写你的获取详情逻辑
|
// 获取用户详情逻辑
|
||||||
const res = await getUserDetails(params)
|
const res = await getUserDetails(params)
|
||||||
console.log(res)
|
console.log(res)
|
||||||
|
|
||||||
if(res && res.code == 200){
|
if(res && res.code == 200){
|
||||||
if (!res.data) {
|
if (!res.data) {
|
||||||
// this.$message.error('未获取到用户信息');
|
|
||||||
this.noDataTip = true
|
this.noDataTip = true
|
||||||
this.userData.coin = this.userDetailsParams.coin
|
// this.userData.coin = this.userDetailsParams.coin
|
||||||
this.userData.user = this.userDetailsParams.minerUser
|
// this.userData.user = this.userDetailsParams.minerUser
|
||||||
}else{
|
}else{
|
||||||
this.userData = res.data
|
this.userData = res.data
|
||||||
this.userData.shouldOutDate=`${this.userData.shouldOutDate.split("T")[0]} ${this.userData.shouldOutDate.split("T")[1]}`
|
// this.userData.shouldOutDate=`${this.userData.shouldOutDate.split("T")[0]} ${this.userData.shouldOutDate.split("T")[1]}`
|
||||||
this.userData.createDate=`${this.userData.createDate.split("T")[0]} ${this.userData.createDate.split("T")[1]}`
|
// this.userData.createDate=`${this.userData.createDate.split("T")[0]} ${this.userData.createDate.split("T")[1]}`
|
||||||
|
this.historyBalance=res.data.historyBalance
|
||||||
|
this.tableData = res.data.walletInInfo.sort((a, b) => new Date(b.createDate) - new Date(a.createDate));
|
||||||
this.noDataTip = false
|
this.noDataTip = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
this.userDetailsLoading = false
|
this.setLoading('userDetailsLoading', false);
|
||||||
},
|
},
|
||||||
async fetchUserLineChart(params) {
|
async fetchUserLineChart(params) {
|
||||||
const res = await getUserLineChart(params)
|
const res = await getUserLineChart(params)
|
||||||
console.log(res)
|
console.log(res)
|
||||||
|
let xData = []
|
||||||
|
let pvData = []
|
||||||
|
if(res && res.code == 200){
|
||||||
|
|
||||||
|
if (!Array.isArray(res.data) || res.data.length === 0 || !res.data[0].unit) {
|
||||||
|
this.chartShow = false
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.chartShow = true
|
||||||
|
this.lineChartData = res.data
|
||||||
|
this.lineChartData.forEach(item => {
|
||||||
|
item.date = item.date.split("T")[0] + " " + item.date.split("T")[1].split(".")[0]
|
||||||
|
xData.push(item.date)
|
||||||
|
pvData.push(Number(item.pv).toFixed(6))
|
||||||
|
})
|
||||||
|
|
||||||
|
this.option.xAxis.data = xData
|
||||||
|
this.option.series[2].data = pvData
|
||||||
|
this.option.yAxis[0].name = this.lineChartData[0].unit
|
||||||
|
// this.inCharts()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async fetchUserOnlineStatus(params) {
|
async fetchUserOnlineStatus(params) {
|
||||||
const res = await getUserOnlineStatus(params)
|
const res = await getUserOnlineStatus(params)
|
||||||
console.log(res)
|
console.log(res)
|
||||||
|
// let xData = []
|
||||||
|
let offlineNum = []
|
||||||
|
let onlineNum = []
|
||||||
|
if(res && res.code == 200){
|
||||||
|
if (!Array.isArray(res.data) || res.data.length === 0 ) {
|
||||||
|
this.chartShow = false
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.chartShow = true
|
||||||
|
this.onlineStatusData = res.data
|
||||||
|
|
||||||
|
this.onlineStatusData.forEach(item => {
|
||||||
|
offlineNum.push(item.offlineNum)
|
||||||
|
onlineNum.push(item.onlineNum)
|
||||||
|
})
|
||||||
|
this.option.series[0].data = onlineNum
|
||||||
|
this.option.series[1].data = offlineNum
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获取图表数据 - 等待两个接口都完成后再渲染图表
|
||||||
|
*/
|
||||||
|
async fetchChartData() {
|
||||||
|
try {
|
||||||
|
this.setLoading('lineChartLoading', true);
|
||||||
|
|
||||||
|
// 并行调用两个接口,等待都完成
|
||||||
|
await Promise.all([
|
||||||
|
this.fetchUserLineChart(this.lineChartParams),
|
||||||
|
this.fetchUserOnlineStatus(this.onlineStatusParams)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 两个接口都完成后,检查是否有数据再渲染图表
|
||||||
|
if (this.chartShow) {
|
||||||
|
this.inCharts();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取图表数据失败:', error);
|
||||||
|
} finally {
|
||||||
|
this.setLoading('lineChartLoading', false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
goBack(){
|
goBack(){
|
||||||
const lang = this.$i18n.locale;
|
const lang = this.$i18n.locale;
|
||||||
|
@ -109,5 +511,31 @@ export default {
|
||||||
path: `/${lang}/userManagement`,
|
path: `/${lang}/userManagement`,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleLineChatTimesChange(val){
|
||||||
|
console.log(val,'val');
|
||||||
|
if(val){
|
||||||
|
this.lineChartParams.startDate=val[0]
|
||||||
|
this.lineChartParams.endDate=val[1]
|
||||||
|
this.onlineStatusParams.startDate=val[0]
|
||||||
|
this.onlineStatusParams.endDate=val[1]
|
||||||
|
this.userDetailsParams.startDate=val[0]
|
||||||
|
this.userDetailsParams.endDate=val[1]
|
||||||
|
|
||||||
|
}else{
|
||||||
|
this.lineChartParams.startDate=""
|
||||||
|
this.lineChartParams.endDate=""
|
||||||
|
this.onlineStatusParams.startDate=""
|
||||||
|
this.onlineStatusParams.endDate=""
|
||||||
|
this.userDetailsParams.startDate=""
|
||||||
|
this.userDetailsParams.endDate=""
|
||||||
|
}
|
||||||
|
this.fetchUserDetails(this.userDetailsParams);
|
||||||
|
// 等待两个图表相关接口都完成后再调用inCharts
|
||||||
|
this.fetchChartData();
|
||||||
|
},
|
||||||
|
handelTime(time){
|
||||||
|
return time.split("T")[0] + " " + time.split("T")[1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,87 +1,216 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="userDetailsLoading">
|
<div v-loading="userDetailsLoading">
|
||||||
<div class="main-title">用户详情 <span @click="goBack" style="color: #409EFF;cursor: pointer;font-size: 16px;">返回</span> </div>
|
<div class="main-title">
|
||||||
<section class="user-details-box">
|
{{$t('backendSystem.userDetails')}}
|
||||||
<section class="user-details-form">
|
<span
|
||||||
<el-form
|
@click="goBack"
|
||||||
:label-position="labelPosition"
|
style="color: #409eff; cursor: pointer; font-size: 16px;margin-left: 10px;"
|
||||||
:inline="true"
|
>{{$t('backendSystem.return')}}</span
|
||||||
:model="userData"
|
|
||||||
class="demo-form-inline"
|
|
||||||
>
|
>
|
||||||
<el-row>
|
</div>
|
||||||
<el-col :span="8">
|
<section class="user-details-box">
|
||||||
<el-form-item style="width: 80%;" label="币种:" label-width="100px" prop="coin">
|
<!-- <section class="user-details-form">
|
||||||
<el-input disabled v-model="userData.coin"></el-input>
|
<el-form
|
||||||
</el-form-item>
|
:label-position="labelPosition"
|
||||||
</el-col>
|
:inline="true"
|
||||||
<el-col :span="8">
|
:model="userData"
|
||||||
<el-form-item style="width: 80%;" label="挖矿账户:" label-width="100px" prop="user">
|
class="demo-form-inline"
|
||||||
<el-input disabled v-model="userData.user"></el-input>
|
>
|
||||||
</el-form-item>
|
<el-row>
|
||||||
</el-col>
|
<el-col :span="8">
|
||||||
<el-col :span="8">
|
<el-form-item
|
||||||
<el-form-item style="width: 80%;" label="交易金额:" label-width="100px" prop="amount">
|
style="width: 80%"
|
||||||
<el-input disabled v-model="userData.amount"></el-input>
|
:label="$t('backendSystem.coin')"
|
||||||
</el-form-item>
|
label-width="100px"
|
||||||
</el-col>
|
prop="coin"
|
||||||
</el-row>
|
>
|
||||||
<el-row>
|
<el-input disabled v-model="userData.coin"></el-input>
|
||||||
<el-col :span="8">
|
</el-form-item>
|
||||||
<el-form-item
|
</el-col>
|
||||||
label="收益分配日期:"
|
<el-col :span="8">
|
||||||
label-width="100px"
|
<el-form-item
|
||||||
prop="createDate"
|
style="width: 80%"
|
||||||
style="width: 80%;"
|
:label="$t('backendSystem.user')"
|
||||||
|
label-width="100px"
|
||||||
|
prop="user"
|
||||||
|
>
|
||||||
|
<el-input disabled v-model="userData.user"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form-item
|
||||||
|
style="width: 80%"
|
||||||
|
:label="$t('backendSystem.amount')"
|
||||||
|
label-width="100px"
|
||||||
|
prop="amount"
|
||||||
|
>
|
||||||
|
<el-input disabled v-model="userData.amount"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('backendSystem.createDate')"
|
||||||
|
label-width="100px"
|
||||||
|
prop="createDate"
|
||||||
|
style="width: 80%"
|
||||||
|
>
|
||||||
|
<el-input disabled v-model="userData.createDate"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form-item
|
||||||
|
style="width: 80%"
|
||||||
|
:label="$t('backendSystem.maxHeight')"
|
||||||
|
label-width="100px"
|
||||||
|
prop="maxHeight"
|
||||||
|
>
|
||||||
|
<el-input disabled v-model="userData.maxHeight"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form-item
|
||||||
|
style="width: 80%"
|
||||||
|
:label="$t('backendSystem.shouldOutDate')"
|
||||||
|
label-width="100px"
|
||||||
|
prop="shouldOutDate"
|
||||||
|
>
|
||||||
|
<el-input disabled v-model="userData.shouldOutDate"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item
|
||||||
|
style="width: 55%"
|
||||||
|
:label="$t('backendSystem.address')"
|
||||||
|
label-width="100px"
|
||||||
|
prop="address"
|
||||||
|
>
|
||||||
|
<el-input disabled v-model="userData.address"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item
|
||||||
|
style="width: 55%; max-height: 300px; overflow-y: auto"
|
||||||
|
:label="$t('backendSystem.historyAddress')"
|
||||||
|
label-width="100px"
|
||||||
|
prop="address"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
class="history-balance-item"
|
||||||
|
v-for="item in userData.historyBalance"
|
||||||
|
:key="item.balance"
|
||||||
|
>
|
||||||
|
{{ item.balance }}
|
||||||
|
</p>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</section> -->
|
||||||
|
|
||||||
|
|
||||||
|
<el-date-picker
|
||||||
|
v-model="lineChatTimes"
|
||||||
|
type="daterange"
|
||||||
|
:range-separator="$t('backendSystem.to')"
|
||||||
|
:start-placeholder="$t('backendSystem.startDate')"
|
||||||
|
:end-placeholder="$t('backendSystem.endDate')"
|
||||||
|
@change="handleLineChatTimesChange"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
size="small"
|
||||||
|
style="margin-bottom: 18px;"
|
||||||
>
|
>
|
||||||
<el-input disabled v-model="userData.createDate"></el-input>
|
</el-date-picker>
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item style="width: 80%;" label="最大高度:" label-width="100px" prop="maxHeight">
|
|
||||||
<el-input disabled v-model="userData.maxHeight"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item style="width: 80%;" label="实际转账日期:" label-width="100px" prop="shouldOutDate">
|
|
||||||
<el-input disabled v-model="userData.shouldOutDate"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item style="width: 55%;" label="转账地址:" label-width="100px" prop="address">
|
|
||||||
<el-input
|
|
||||||
disabled v-model="userData.address"
|
|
||||||
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
|
|
||||||
<el-row>
|
<el-table
|
||||||
<el-col :span="24">
|
:data="tableData"
|
||||||
<el-form-item style="width: 55%; max-height: 300px;overflow-y: auto;" label="历史支付地址:" label-width="100px" prop="address">
|
border
|
||||||
<p class="history-balance-item" v-for="item in userData.historyBalance" :key="item.balance">{{item.balance}}</p>
|
|
||||||
</el-form-item>
|
:header-cell-style="{ 'text-align': 'center' }"
|
||||||
</el-col>
|
:cell-style="{ 'text-align': 'center' }"
|
||||||
</el-row>
|
height="42vh"
|
||||||
|
>
|
||||||
|
<el-table-column prop="createDate" :label="$t('backendSystem.createDate')" width="160" >
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ handelTime(scope.row.createDate ) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="shouldOutDate" :label="$t('backendSystem.shouldOutDate')" width="180" show-overflow-tooltip >
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ handelTime(scope.row.shouldOutDate ) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="coin" :label="$t('backendSystem.coin2')" width="100" show-overflow-tooltip>
|
||||||
|
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="amount" :label="$t('backendSystem.amount2')" width="200" show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column prop="user" :label="$t('backendSystem.minerUser2')" width="180" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="address" :label="$t('backendSystem.address')" show-overflow-tooltip />
|
||||||
|
|
||||||
|
<el-table-column prop="maxHeight" :label="$t('backendSystem.maxHeight')" width="180" show-overflow-tooltip />
|
||||||
|
|
||||||
|
|
||||||
</el-form>
|
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
|
||||||
|
<section class="chartBox">
|
||||||
|
<div class="lineChartBox">
|
||||||
|
<div class="lineChartBox-header">
|
||||||
|
<div class="lineChartBox-title">{{$t('backendSystem.chartTitle')}}</div>
|
||||||
|
<!-- <el-date-picker
|
||||||
|
v-model="lineChatTimes"
|
||||||
|
type="daterange"
|
||||||
|
:range-separator="$t('backendSystem.to')"
|
||||||
|
:start-placeholder="$t('backendSystem.startDate')"
|
||||||
|
:end-placeholder="$t('backendSystem.endDate')"
|
||||||
|
@change="handleLineChatTimesChange"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
size="small"
|
||||||
|
:disabled="!chartShow"
|
||||||
|
>
|
||||||
|
</el-date-picker> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="lineChartBox-content"
|
||||||
|
style="width: 100%; height: 500px; margin-top: 35px;"
|
||||||
|
>
|
||||||
|
<div v-if="!chartShow" style="text-align: center;margin-top: 200px;color: #ccc;">{{$t('backendSystem.noData')}}</div>
|
||||||
|
<div v-else v-loading="lineChartLoading" id="lineChart" style="width: 100%; height: 100%"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<div
|
||||||
|
style="width: 100%; max-height: 300px; overflow-y: auto;"
|
||||||
|
>
|
||||||
|
<h3 style="margin-bottom: 20px;">{{$t('backendSystem.historyAddress')}}</h3>
|
||||||
|
|
||||||
|
|
||||||
|
<p
|
||||||
|
class="history-balance-item"
|
||||||
|
v-for="item in historyBalance"
|
||||||
|
:key="item.balance"
|
||||||
|
>
|
||||||
|
{{ item.balance }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="chartBox">
|
|
||||||
<div class="lineChartBox">用户挖矿曲线图</div>
|
|
||||||
<div class="barChartBox">柱状图</div>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -100,7 +229,7 @@ export default {
|
||||||
color: #333;
|
color: #333;
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
}
|
}
|
||||||
.user-details-box{
|
.user-details-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
@ -124,55 +253,76 @@ export default {
|
||||||
// background: palegoldenrod;
|
// background: palegoldenrod;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-data-tip{
|
.no-data-tip {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #999;
|
color: #999;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-balance-item{
|
.history-balance-item {
|
||||||
|
display: inline-block; /* 让宽度随内容自适应 */
|
||||||
margin: 0;
|
background: #e7dff3;
|
||||||
padding: 0;
|
padding: 8px 20px;
|
||||||
background:#E7DFF3 ;
|
|
||||||
padding: 0px 20px;
|
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
color: rgba(0,0,0,0.6);
|
color: rgba(0, 0, 0, 0.6);
|
||||||
|
/* width: auto; 其实可以省略,inline-block默认就是auto */
|
||||||
|
/* 防止flex布局下被拉伸 */
|
||||||
|
flex: none;
|
||||||
|
align-self: flex-start;
|
||||||
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-form-item__label {
|
::v-deep .el-form-item__label {
|
||||||
// color: #409EFF; /* 例如设置为 Element UI 主色 */
|
// color: #409EFF; /* 例如设置为 Element UI 主色 */
|
||||||
font-weight: bold; /* 加粗 */
|
font-weight: bold; /* 加粗 */
|
||||||
font-size: 16px; /* 字号 */
|
font-size: 16px; /* 字号 */
|
||||||
letter-spacing: 1px; /* 字间距 */
|
letter-spacing: 1px; /* 字间距 */
|
||||||
/* 你可以根据需要添加更多样式 */
|
/* 你可以根据需要添加更多样式 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.chartBox{
|
.chartBox {
|
||||||
width: 80vw;
|
width: 80vw;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
// background: palegoldenrod;
|
// background: palegoldenrod;
|
||||||
height: 800px;
|
|
||||||
|
|
||||||
|
padding: 0;
|
||||||
|
margin: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lineChartBox {
|
||||||
|
width: 97%;
|
||||||
|
height: 80%;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
box-shadow: 0px 0px 1px 1px #ccc;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.lineChartBox-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: rgba(0, 0, 0, 0.6);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.lineChartBox-header{
|
||||||
display: flex;
|
display: flex;
|
||||||
align-content: center;
|
justify-content: space-between;
|
||||||
justify-content: space-around;
|
align-items: center;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
padding:1% 5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lineChartBox{
|
</style>
|
||||||
width: 49%;
|
|
||||||
height: 100%;
|
<style>
|
||||||
background: palegoldenrod;
|
.el-date-editor .el-range-separator {
|
||||||
}
|
padding: 0 !important;
|
||||||
.barChartBox{
|
color: #333 !important;
|
||||||
width: 49%;
|
|
||||||
height: 100%;
|
|
||||||
background: pink;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -24,17 +24,17 @@ export default {
|
||||||
user: [
|
user: [
|
||||||
{
|
{
|
||||||
type: 'email',
|
type: 'email',
|
||||||
message: '请输入正确的邮箱地址',
|
message: this.$t('backendSystem.pleaseInputCorrectEmail'),
|
||||||
trigger: ['blur', 'change']
|
trigger: ['blur', 'change']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
emailRules: {
|
emailRules: {
|
||||||
subject: [
|
subject: [
|
||||||
{ required: true, message: '请输入邮件主题', trigger: 'blur' }
|
{ required: true, message: this.$t('backendSystem.pleaseInputSubject'), trigger: 'blur' }
|
||||||
],
|
],
|
||||||
text: [
|
text: [
|
||||||
{ required: true, message: '请输入邮件内容', trigger: 'blur' }
|
{ required: true, message: this.$t('backendSystem.pleaseInputText'), trigger: 'blur' }
|
||||||
],
|
],
|
||||||
to: [
|
to: [
|
||||||
{
|
{
|
||||||
|
@ -56,7 +56,7 @@ export default {
|
||||||
// 检查格式
|
// 检查格式
|
||||||
for (let email of emails) {
|
for (let email of emails) {
|
||||||
if (!emailReg.test(email)) {
|
if (!emailReg.test(email)) {
|
||||||
callback(new Error('请输入正确的邮箱地址,多个邮箱用逗号分隔'));
|
callback(new Error(this.$t('backendSystem.pleaseInputCorrectEmail2')));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ export default {
|
||||||
for (let email of emails) {
|
for (let email of emails) {
|
||||||
const lower = email.toLowerCase();
|
const lower = email.toLowerCase();
|
||||||
if (lowerSet.has(lower)) {
|
if (lowerSet.has(lower)) {
|
||||||
callback(new Error('存在重复邮箱,请检查'));
|
callback(new Error(this.$t('backendSystem.existDuplicateEmail')));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lowerSet.add(lower);
|
lowerSet.add(lower);
|
||||||
|
@ -83,6 +83,9 @@ export default {
|
||||||
to:"",
|
to:"",
|
||||||
},
|
},
|
||||||
sendEmailLoading: false,
|
sendEmailLoading: false,
|
||||||
|
total: 0,
|
||||||
|
pageSizes: [50, 100, 300],
|
||||||
|
currentPage: 1,
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -94,11 +97,11 @@ export default {
|
||||||
}catch(e){
|
}catch(e){
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
if (token) {
|
if (!token) {
|
||||||
|
this.$router.push({ path: `/${lang}/login` });
|
||||||
|
|
||||||
this.fetchUserList(this.userListParams);
|
|
||||||
}
|
}
|
||||||
|
this.fetchUserList(this.userListParams);
|
||||||
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
||||||
window.addEventListener("setItem", () => {
|
window.addEventListener("setItem", () => {
|
||||||
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
||||||
|
@ -110,9 +113,12 @@ export default {
|
||||||
|
|
||||||
this.setLoading('userManagementLoading', true);
|
this.setLoading('userManagementLoading', true);
|
||||||
const data = await getUserList(params);
|
const data = await getUserList(params);
|
||||||
|
console.log(data,'data');
|
||||||
|
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.tableData = data.rows;
|
this.tableData = data.rows;
|
||||||
|
this.total = data.total;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('userManagementLoading', false);
|
this.setLoading('userManagementLoading', false);
|
||||||
|
@ -124,7 +130,7 @@ export default {
|
||||||
|
|
||||||
|
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.$message.success('发送成功');
|
this.$message.success(this.$t('backendSystem.sendSuccess'));
|
||||||
this.dialogVisible = false;
|
this.dialogVisible = false;
|
||||||
for (const key in this.senParams) {
|
for (const key in this.senParams) {
|
||||||
this.senParams[key] = "";
|
this.senParams[key] = "";
|
||||||
|
@ -146,7 +152,11 @@ export default {
|
||||||
|
|
||||||
},
|
},
|
||||||
handelImg(coin) {
|
handelImg(coin) {
|
||||||
return this.currencyList.find(item => item.value === coin)?.imgUrl || '';
|
if(this.currencyList &&this.currencyList.length > 0 && coin){
|
||||||
|
return this.currencyList.find(item => item.value === coin)?.imgUrl || '';
|
||||||
|
}else{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handelQuery() {
|
handelQuery() {
|
||||||
this.$refs.formRef.validate((valid) => {
|
this.$refs.formRef.validate((valid) => {
|
||||||
|
@ -158,7 +168,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.userListParams.minerUser && !this.userListParams.user) {
|
if (!this.userListParams.minerUser && !this.userListParams.user) {
|
||||||
this.$message.error('请输入查询条件(挖矿账号、邮箱)');
|
this.$message.error(this.$t('backendSystem.pleaseInputQueryConditions'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.fetchUserList(this.userListParams);
|
this.fetchUserList(this.userListParams);
|
||||||
|
@ -218,6 +228,23 @@ export default {
|
||||||
|
|
||||||
// 保存ID到localStorage
|
// 保存ID到localStorage
|
||||||
localStorage.setItem("userDetailsParams",JSON.stringify(obj));
|
localStorage.setItem("userDetailsParams",JSON.stringify(obj));
|
||||||
}
|
},
|
||||||
|
|
||||||
|
handleSizeChange(val) {
|
||||||
|
console.log(`每页 ${val} 条`);
|
||||||
|
this.userListParams.pageSize = val
|
||||||
|
this.userListParams.pageNum = 1
|
||||||
|
this.currentPage = 1
|
||||||
|
this.fetchUserList(this.userListParams);
|
||||||
|
|
||||||
|
},
|
||||||
|
handleCurrentChange(val) {
|
||||||
|
console.log(`当前页: ${val}`);
|
||||||
|
this.userListParams.pageNum = val
|
||||||
|
this.fetchUserList(this.userListParams);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="userManagementLoading">
|
<div v-loading="userManagementLoading">
|
||||||
<div class="main-title">注册用户管理</div>
|
<div class="main-title">{{$t('backendSystem.userManagementTitle')}}</div>
|
||||||
|
|
||||||
<el-form :inline="true" :model="userListParams" class="demo-form-inline" :rules="rules" ref="formRef">
|
<el-form :inline="true" :model="userListParams" class="demo-form-inline" :rules="rules" ref="formRef">
|
||||||
<el-form-item label="币种:" prop="coin">
|
<el-form-item :label="$t('backendSystem.coin')" prop="coin">
|
||||||
<el-select
|
<el-select
|
||||||
class="input"
|
class="input"
|
||||||
|
|
||||||
|
@ -28,21 +28,21 @@
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="挖矿账号:" style="margin-left: 5vw" prop="minerUser">
|
<el-form-item :label="$t('backendSystem.user')" style="margin-left: 5vw" prop="minerUser">
|
||||||
<el-input v-model="userListParams.minerUser" placeholder="挖矿账号" clearable @clear="handleInputClear"></el-input>
|
<el-input v-model="userListParams.minerUser" :placeholder="$t('backendSystem.pleaseInput')" clearable @clear="handleInputClear"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="邮箱:" style="margin-left: 5vw" prop="user">
|
<el-form-item :label="$t('backendSystem.email')" style="margin-left: 5vw" prop="user">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="userListParams.user"
|
v-model="userListParams.user"
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="邮箱"
|
:placeholder="$t('backendSystem.pleaseInput')"
|
||||||
clearable
|
clearable
|
||||||
@clear="handleInputClear"
|
@clear="handleInputClear"
|
||||||
></el-input>
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item style="margin-left: 1vw">
|
<el-form-item style="margin-left: 1vw">
|
||||||
<el-button type="primary" @click="handelQuery">查询</el-button>
|
<el-button type="primary" @click="handelQuery">{{$t('backendSystem.query')}}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-table
|
<el-table
|
||||||
|
@ -51,10 +51,10 @@
|
||||||
style="width: 100%; margin-bottom: 18px"
|
style="width: 100%; margin-bottom: 18px"
|
||||||
:header-cell-style="{ 'text-align': 'center' }"
|
:header-cell-style="{ 'text-align': 'center' }"
|
||||||
:cell-style="{ 'text-align': 'center' }"
|
:cell-style="{ 'text-align': 'center' }"
|
||||||
height="65vh"
|
height="60vh"
|
||||||
>
|
>
|
||||||
<el-table-column prop="id" label="ID" width="60" />
|
<el-table-column prop="id" label="ID" width="60" />
|
||||||
<el-table-column prop="coin" label="币种" width="100" show-overflow-tooltip>
|
<el-table-column prop="coin" :label="$t('backendSystem.coin2')" width="100" show-overflow-tooltip>
|
||||||
<template slot-scope="scope" >
|
<template slot-scope="scope" >
|
||||||
<div style="display: flex; align-items: center;justify-content: center;">
|
<div style="display: flex; align-items: center;justify-content: center;">
|
||||||
<img :src="handelImg(scope.row.coin)" style="width: 20px" />
|
<img :src="handelImg(scope.row.coin)" style="width: 20px" />
|
||||||
|
@ -62,59 +62,76 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="user" label="用户邮箱" width="200" show-overflow-tooltip/>
|
<el-table-column prop="user" :label="$t('backendSystem.email2')" width="200" show-overflow-tooltip/>
|
||||||
<el-table-column prop="amount" label="最小起付金额" width="100" show-overflow-tooltip/>
|
<el-table-column prop="amount" :label="$t('backendSystem.amount2')" width="150" show-overflow-tooltip/>
|
||||||
<el-table-column prop="status" label="用户状态" width="80">
|
<el-table-column prop="status" :label="$t('backendSystem.status2')" width="100">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag :type="scope.row.status === '1' ? 'success' : 'danger'">{{
|
<el-tag :type="scope.row.status === '1' ? 'success' : 'danger'">{{
|
||||||
scope.row.status == "0" ? "正常" : "删除"
|
scope.row.status == "0" ? $t('backendSystem.normal') : $t('backendSystem.delete')
|
||||||
}}</el-tag>
|
}}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="minerUser" label="挖矿账号" width="180" show-overflow-tooltip/>
|
<el-table-column prop="minerUser" :label="$t('backendSystem.minerUser2')" width="180" show-overflow-tooltip/>
|
||||||
<el-table-column prop="balance" label="支付地址" show-overflow-tooltip />
|
<el-table-column prop="balance" :label="$t('backendSystem.balance2')" show-overflow-tooltip />
|
||||||
<el-table-column prop="active" label="是否自动提现" width="80" show-overflow-tooltip>
|
<el-table-column prop="active" :label="$t('backendSystem.active2')" width="100" show-overflow-tooltip>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag :type="scope.row.active === '1' ? 'success' : 'danger'">{{
|
<el-tag :type="scope.row.active === '1' ? 'success' : 'danger'">{{
|
||||||
scope.row.active == "0" ? "是" : "否"
|
scope.row.active == "0" ? $t('backendSystem.yes') : $t('backendSystem.no')
|
||||||
}}</el-tag>
|
}}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column :label="$t('backendSystem.operation')" width="180">
|
<el-table-column :label="$t('backendSystem.operation')" width="200">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" @click="handleDetails(scope.row)" type="primary" plain>详情</el-button>
|
<el-button size="mini" @click="handleDetails(scope.row)" type="primary" plain>{{$t('backendSystem.Details')}}</el-button>
|
||||||
<el-button size="mini" @click="sendEmail(scope.row)" style="color: #651fff; border: 1px solid #651fff"
|
<el-button size="mini" @click="sendEmail(scope.row)" style="color: #651fff; border: 1px solid #651fff"
|
||||||
>发送邮件</el-button
|
>{{$t('backendSystem.sendEmail')}}</el-button
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24" style="display: flex; justify-content: center;">
|
||||||
|
<el-pagination
|
||||||
|
style="margin:0 auto;margin-top: 10px;"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
:current-page.sync="currentPage"
|
||||||
|
:page-sizes="pageSizes"
|
||||||
|
:page-size="userListParams.pageSize"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total">
|
||||||
|
</el-pagination>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 发送邮箱弹窗-->
|
<!-- 发送邮箱弹窗-->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="邮件内容"
|
:title="$t('backendSystem.emailContent')"
|
||||||
:visible.sync="dialogVisible"
|
:visible.sync="dialogVisible"
|
||||||
width="50%"
|
width="50%"
|
||||||
:before-close="handleClose"
|
:before-close="handleClose"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<el-form :model="senParams" ref="formRef" :rules="emailRules">
|
<el-form :model="senParams" ref="formRef" :rules="emailRules">
|
||||||
<el-form-item label="收件人" prop="to">
|
<el-form-item :label="$t('backendSystem.recipient')" prop="to">
|
||||||
<el-input maxlength="500" resize="none" v-model="senParams.to" type="textarea" :rows="2" />
|
<el-input maxlength="500" resize="none" v-model="senParams.to" type="textarea" :rows="2" />
|
||||||
<div style="color: #999; font-size: 12px; margin-top: 4px;">可输入多个邮箱,用逗号隔开</div>
|
<div style="color: #999; font-size: 12px; margin-top: 4px;">{{$t('backendSystem.emailRemind')}}</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="邮件主题" prop="subject">
|
<el-form-item :label="$t('backendSystem.subject')" prop="subject">
|
||||||
<el-input resize="none" maxlength="300" show-word-limit v-model="senParams.subject" type="textarea" :rows="3" />
|
<el-input resize="none" maxlength="300" show-word-limit v-model="senParams.subject" type="textarea" :rows="3" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="邮件内容" prop="text">
|
<el-form-item :label="$t('backendSystem.text')" prop="text">
|
||||||
<el-input resize="none" maxlength="600" show-word-limit v-model="senParams.text" type="textarea" :rows="8" />
|
<el-input resize="none" maxlength="600" show-word-limit v-model="senParams.text" type="textarea" :rows="8" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button @click="handleClose">{{$t("backendSystem.cancel")}}</el-button>
|
<el-button @click="handleClose">{{$t("backendSystem.cancel")}}</el-button>
|
||||||
<el-button type="primary" :loading="sendEmailLoading" @click="sureSendEmail">发送</el-button>
|
<el-button type="primary" :loading="sendEmailLoading" @click="sureSendEmail">{{$t("backendSystem.send")}}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@
|
||||||
:cell-style="{ 'text-align': 'center' }"
|
:cell-style="{ 'text-align': 'center' }"
|
||||||
:data="from1"
|
:data="from1"
|
||||||
style="width: 100%; text-transform: none;"
|
style="width: 100%; text-transform: none;"
|
||||||
max-height="600"
|
max-height="550"
|
||||||
stripe
|
stripe
|
||||||
>
|
>
|
||||||
<el-table-column prop="id" :label="$t(`work.WorkID`)" > </el-table-column>
|
<el-table-column prop="id" :label="$t(`work.WorkID`)" > </el-table-column>
|
||||||
|
@ -290,7 +290,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
<el-row type="flex" justify="center" style="margin-top: 15px;">
|
<el-row type="flex" justify="center" style="margin-top: 20px;margin-bottom: 10px;">
|
||||||
<el-col :span="10">
|
<el-col :span="10">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
@size-change="handleSizeChange"
|
@size-change="handleSizeChange"
|
||||||
|
|
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 @@
|
||||||
<!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.e36ba8a9.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.7d4ad37d.js></script><script defer src=/js/app-d363ae0c.603ece39.js></script><script defer src=/js/app-5c551db8.baf3658a.js></script><script defer src=/js/app-b4c4f6ec.94c0ddb2.js></script><script defer src=/js/app-45954fd3.53c0df94.js></script><script defer src=/js/app-72600b29.7a20ccca.js></script><script defer src=/js/app-f035d474.92e1d288.js></script><script defer src=/js/app-7023e5b0.a956a90d.js></script><script defer src=/js/app-113c6c50.6af405db.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/app-189e7968.abee2a01.css rel=stylesheet><link href=/css/app-b4c4f6ec.6e507abe.css rel=stylesheet><link href=/css/app-45954fd3.86c0fd20.css rel=stylesheet><link href=/css/app-72600b29.8bee31b9.css rel=stylesheet><link href=/css/app-f035d474.0348646a.css rel=stylesheet><link href=/css/app-7023e5b0.87f1eef9.css rel=stylesheet><link href=/css/app-113c6c50.59d737ac.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.2598fd7a.js></script><script defer src=/js/app-d363ae0c.40a47f4f.js></script><script defer src=/js/app-5c551db8.89b85533.js></script><script defer src=/js/app-b4c4f6ec.94c0ddb2.js></script><script defer src=/js/app-45954fd3.508cc9ca.js></script><script defer src=/js/app-72600b29.ee6f16e3.js></script><script defer src=/js/app-f035d474.34668127.js></script><script defer src=/js/app-7023e5b0.a956a90d.js></script><script defer src=/js/app-113c6c50.3dff300c.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/app-189e7968.9dadb641.css rel=stylesheet><link href=/css/app-b4c4f6ec.6e507abe.css rel=stylesheet><link href=/css/app-45954fd3.ebaa14f6.css rel=stylesheet><link href=/css/app-72600b29.6fce1895.css rel=stylesheet><link href=/css/app-f035d474.0348646a.css rel=stylesheet><link href=/css/app-7023e5b0.87f1eef9.css rel=stylesheet><link href=/css/app-113c6c50.1696c00b.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.
|
@ -1 +1 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://m2pool.com/en</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-06-27T06:12:42.085Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-06-27T06:12:42.085Z</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-07-03T08:52:19.108Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-07-03T08:52:19.108Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-07-03T08:52:19.108Z</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-06-27T06:12:42.057Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-06-27T06:12:42.067Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-06-27T06:12:42.067Z</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-07-03T08:52:19.100Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-07-03T08:52:19.100Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>
|
Binary file not shown.
Loading…
Reference in New Issue