电脑端聊天客服系统完成
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view class="page" />
|
||||
<!-- <ChatWidget v-if="!$route.path.includes('/customerService') && !$isMobile" /> -->
|
||||
<ChatWidget v-if="!$route.path.includes('/customerService') && !$isMobile" />
|
||||
</div>
|
||||
</template>
|
||||
<script >
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -89,6 +89,8 @@ export const ChatWidget_zh = {
|
||||
serverLimitError:"服务器连接数已达上限,请稍后刷新重试",
|
||||
identityError:"用户身份设置失败,请刷新页面重试",
|
||||
emailError:"用户信息获取失败,请刷新页面重试",
|
||||
refreshPage:"刷新页面",
|
||||
reconnectSuccess:"重新连接成功",
|
||||
},
|
||||
|
||||
|
||||
@@ -186,6 +188,8 @@ export const ChatWidget_en = {
|
||||
serverLimitError:"Connection limit reached, please try again later",
|
||||
identityError:"Failed to set user identity, please refresh page",
|
||||
emailError:"Failed to get user information, please refresh page",
|
||||
refreshPage:"Refresh page",
|
||||
reconnectSuccess:"Reconnect successfully",
|
||||
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,6 +4,13 @@ import { Notification, MessageBox, Message } from 'element-ui'
|
||||
import loadingManager from './loadingManager';
|
||||
import errorNotificationManager from './errorNotificationManager';
|
||||
|
||||
|
||||
const pendingRequestMap = new Map(); //处理Request aborted 错误
|
||||
|
||||
function getRequestKey(config) { //处理Request aborted 错误 生成唯一 key 的函数
|
||||
const { url, method, params, data } = config;
|
||||
return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&');
|
||||
}
|
||||
// 创建axios实例
|
||||
const service = axios.create({
|
||||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||
@@ -143,9 +150,6 @@ window.addEventListener('online', () => {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// 使用错误提示管理器控制网络断开提示
|
||||
window.addEventListener('offline', () => {
|
||||
if (window.vm && window.vm.$message && errorNotificationManager.canShowError('networkOffline')) {
|
||||
@@ -215,6 +219,22 @@ service.interceptors.request.use(config => {
|
||||
config.params = {};
|
||||
config.url = url;
|
||||
}
|
||||
|
||||
// 生成请求唯一key 处理Request aborted 错误
|
||||
const requestKey = getRequestKey(config);
|
||||
|
||||
// 如果有相同请求,先取消 处理Request aborted 错误
|
||||
if (pendingRequestMap.has(requestKey)) {
|
||||
const cancel = pendingRequestMap.get(requestKey);
|
||||
cancel(); // 取消上一次请求
|
||||
pendingRequestMap.delete(requestKey);
|
||||
}
|
||||
|
||||
// 创建新的CancelToken 处理Request aborted 错误
|
||||
config.cancelToken = new axios.CancelToken(cancel => {
|
||||
pendingRequestMap.set(requestKey, cancel);
|
||||
});
|
||||
|
||||
return config
|
||||
}, error => {
|
||||
Promise.reject(error)
|
||||
@@ -222,6 +242,10 @@ service.interceptors.request.use(config => {
|
||||
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use(res => {
|
||||
|
||||
// 请求完成后移除
|
||||
const requestKey = getRequestKey(res.config);
|
||||
pendingRequestMap.delete(requestKey);
|
||||
// 未设置状态码则默认成功状态
|
||||
const code = res.data.code || 200;
|
||||
// 获取错误信息
|
||||
@@ -284,8 +308,15 @@ service.interceptors.response.use(res => {
|
||||
|
||||
},
|
||||
error => {
|
||||
|
||||
|
||||
if (error.message && error.message.includes('canceled') || error.message.includes('Request aborted')) {
|
||||
// 主动取消的请求,直接忽略,不提示
|
||||
return Promise.reject(error);
|
||||
}
|
||||
// 请求异常也要移除 处理Request aborted 错误
|
||||
if (error.config) {
|
||||
const requestKey = getRequestKey(error.config);
|
||||
pendingRequestMap.delete(requestKey);
|
||||
}
|
||||
|
||||
|
||||
let { message } = error;
|
||||
|
||||
@@ -89,13 +89,13 @@
|
||||
<p>{{ $t(`ServiceTerms.clauseTermination2`) }}</p>
|
||||
</div>
|
||||
</section>
|
||||
<section class="clauseBox">
|
||||
<!-- <section class="clauseBox">
|
||||
<h5>{{ $t(`ServiceTerms.title11`) }}</h5>
|
||||
<div class="textBox">
|
||||
<p>{{ $t(`ServiceTerms.clauseLaw1`) }}</p>
|
||||
<p>{{ $t(`ServiceTerms.clauseLaw2`) }}</p>
|
||||
</div>
|
||||
</section>
|
||||
</section> -->
|
||||
|
||||
</section>
|
||||
|
||||
@@ -189,13 +189,13 @@
|
||||
<p>{{ $t(`ServiceTerms.clauseTermination2`) }}</p>
|
||||
</div>
|
||||
</section>
|
||||
<section class="clauseBox">
|
||||
<!-- <section class="clauseBox">
|
||||
<h3>{{ $t(`ServiceTerms.title11`) }}</h3>
|
||||
<div class="textBox">
|
||||
<p>{{ $t(`ServiceTerms.clauseLaw1`) }}</p>
|
||||
<p>{{ $t(`ServiceTerms.clauseLaw2`) }}</p>
|
||||
</div>
|
||||
</section>
|
||||
</section> -->
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -276,20 +276,20 @@ export default {
|
||||
name: "GH/s",
|
||||
nameTextStyle: {
|
||||
padding: [0, 0, 0, -40],
|
||||
},
|
||||
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
|
||||
}
|
||||
}
|
||||
// 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 data
|
||||
// }
|
||||
// }
|
||||
},
|
||||
{
|
||||
position: "right",
|
||||
@@ -833,6 +833,7 @@ export default {
|
||||
const maxValue = Math.max(...this.option.series[0].data); // 获取数据最大值
|
||||
const formatter = yAxis.axisLabel.formatter;
|
||||
const formattedValue = formatter(maxValue); // 格式化最大值
|
||||
|
||||
|
||||
// 创建一个临时 DOM 元素计算宽度
|
||||
const tempDiv = document.createElement('div');
|
||||
@@ -847,11 +848,30 @@ export default {
|
||||
// 动态设置 grid.left,加上安全边距
|
||||
const safeMargin = 20;
|
||||
this.option.grid.left = labelWidth + safeMargin + 'px';
|
||||
// this.$nextTick(
|
||||
// // 更新图表
|
||||
// this.inCharts()
|
||||
|
||||
// )
|
||||
|
||||
// ------------全网算力图---------------
|
||||
//
|
||||
|
||||
const yAxis2 = this.minerOption.yAxis[0]; // 第一个 Y 轴
|
||||
const maxValue2 = Math.max(...this.minerOption.series[0].data); // 获取数据最大值
|
||||
const formatter2 = yAxis2.axisLabel.formatter;
|
||||
const formattedValue2 = formatter2(maxValue2); // 格式化最大值
|
||||
|
||||
|
||||
// 创建一个临时 DOM 元素计算宽度
|
||||
const tempDiv2 = document.createElement('div');
|
||||
tempDiv2.style.position = 'absolute';
|
||||
tempDiv2.style.visibility = 'hidden';
|
||||
tempDiv2.style.fontSize = '12px'; // 与 axisLabel.fontSize 一致
|
||||
tempDiv2.innerText = formattedValue2;
|
||||
document.body.appendChild(tempDiv2);
|
||||
const labelWidth2 = tempDiv2.offsetWidth;
|
||||
document.body.removeChild(tempDiv2);
|
||||
// 动态设置 grid.left,加上安全边距
|
||||
const safeMargin2 = 20;
|
||||
this.minerOption.grid.left = labelWidth2 + safeMargin2 + 'px';
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -888,6 +908,30 @@ export default {
|
||||
|
||||
|
||||
methods: {
|
||||
|
||||
handelOptionYAxis(option){
|
||||
const yAxis = option.yAxis[0]; // 第一个 Y 轴
|
||||
const maxValue = Math.max(...option.series[0].data); // 获取数据最大值
|
||||
const formatter = yAxis.axisLabel.formatter;
|
||||
const formattedValue = formatter(maxValue); // 格式化最大值
|
||||
|
||||
|
||||
// 创建一个临时 DOM 元素计算宽度
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.style.position = 'absolute';
|
||||
tempDiv.style.visibility = 'hidden';
|
||||
tempDiv.style.fontSize = '12px'; // 与 axisLabel.fontSize 一致
|
||||
tempDiv.innerText = formattedValue;
|
||||
document.body.appendChild(tempDiv);
|
||||
const labelWidth = tempDiv.offsetWidth;
|
||||
document.body.removeChild(tempDiv);
|
||||
|
||||
// 动态设置 grid.left,加上安全边距
|
||||
const safeMargin = 20;
|
||||
option.grid.left = labelWidth + safeMargin + 'px';
|
||||
|
||||
return option
|
||||
},
|
||||
slideLeft() {
|
||||
const allLength = this.currencyList.length * 120
|
||||
const boxLength = document.getElementById('list-box').clientWidth
|
||||
@@ -940,7 +984,7 @@ export default {
|
||||
this.MinerChart = echarts.init(document.getElementById("minerChart"));
|
||||
}
|
||||
|
||||
|
||||
this.minerOption= this.handelOptionYAxis(this.minerOption) // Y轴文字显示动态调整grid.left
|
||||
this.minerOption.series[0].name = this.$t(`home.networkPower`)
|
||||
this.minerOption.series[1].name = this.$t(`home.currencyPrice`)
|
||||
this.MinerChart.setOption(this.minerOption);
|
||||
|
||||
@@ -214,6 +214,7 @@ import {
|
||||
import { encryption } from "../../utils/fun";
|
||||
import { getAccountList } from "../../api/personalCenter";
|
||||
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -372,6 +373,11 @@ export default {
|
||||
JSON.stringify(data.data.access_token)
|
||||
);
|
||||
|
||||
|
||||
// 等待一小段时间确保写入完成
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
// 登录成功后
|
||||
this.$bus.$emit('user-logged-in'); // 触发登录成功全局事件
|
||||
this.fetchAccountList();
|
||||
this.fetchAccountGradeList();
|
||||
this.fetchJurisdiction();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import { getCheck,getAddBalace, getAddMinerAccount, getAccountList, getDelMinerAccount, getMinerAccountBalance, getCheckAccount,getCheckBalance,getIfBind } from "../../../api/personalCenter"
|
||||
import {getAccountGradeList } from "../../../api/login"
|
||||
import { Debounce,throttle }from "../../../utils/publicMethods";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -542,13 +543,7 @@ export default {
|
||||
}
|
||||
|
||||
},
|
||||
confirmAdd() {
|
||||
// this.accountList.push({
|
||||
// account: this.params.account,
|
||||
// miningPool: this.params.miningPool,
|
||||
// currency: this.params.miningPool,
|
||||
// remarks: this.params.remarks,
|
||||
// })
|
||||
confirmAdd:Debounce(function(){
|
||||
if (!this.AccountParams.ma) {
|
||||
this.$message({
|
||||
message: this.$t(`personal.accountNumber`),
|
||||
@@ -600,12 +595,66 @@ export default {
|
||||
}
|
||||
|
||||
this.fetchCheck({ coin: this.AccountParams.coin, ma: this.AccountParams.ma,balance: this.AccountParams.balance})
|
||||
// this.fetchCheckAccount({ coin: this.AccountParams.coin, ma: this.AccountParams.ma })
|
||||
},200),
|
||||
// confirmAdd() {
|
||||
|
||||
// if (!this.AccountParams.ma) {
|
||||
// this.$message({
|
||||
// message: this.$t(`personal.accountNumber`),
|
||||
// type: "error",
|
||||
// showClose: true
|
||||
// });
|
||||
// return
|
||||
// }
|
||||
// if (!this.AccountParams.balance) {
|
||||
// this.$message({
|
||||
// message: this.$t(`personal.inputWalletAddress`),
|
||||
// type: "error",
|
||||
// showClose: true
|
||||
// });
|
||||
// return
|
||||
// }
|
||||
// if (!this.AccountParams.coin) {
|
||||
// this.$message({
|
||||
// message:this.$t(`personal.selectCurrency`),
|
||||
// type: "error",
|
||||
// showClose: true
|
||||
// });
|
||||
// return
|
||||
// }
|
||||
|
||||
// if (!this.AccountParams.code && this.isItBound) {
|
||||
// this.$message({
|
||||
// showClose: true,
|
||||
// message: this.$t(`personal.gCode`),
|
||||
// type: 'error'
|
||||
// });
|
||||
|
||||
// return
|
||||
// }
|
||||
|
||||
// // 账户只能输入字母、数字、下划线,且不能以数字开头,长度不小于4位,不大于24位
|
||||
// const regexAccount=/^[a-zA-Z_][a-zA-Z0-9_]{3,23}$/
|
||||
|
||||
// const PasswordIsValid = regexAccount.test(this.AccountParams.ma);
|
||||
// if (!PasswordIsValid) {
|
||||
// // 如果输入不符合要求,可以根据具体需求给出错误提示或进行其他处理
|
||||
// this.$message({
|
||||
// message: this.$t(`personal.accountFormat`),
|
||||
// type: "error",
|
||||
// showClose: true
|
||||
// });
|
||||
|
||||
// return;
|
||||
// }
|
||||
|
||||
// this.fetchCheck({ coin: this.AccountParams.coin, ma: this.AccountParams.ma,balance: this.AccountParams.balance})
|
||||
// // this.fetchCheckAccount({ coin: this.AccountParams.coin, ma: this.AccountParams.ma })
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
// },
|
||||
handelAddClose(){
|
||||
for (let key in this.AccountParams) {
|
||||
this.AccountParams[key] = "";
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
import { getResetPwd, getResetPwdCode } from "../../api/login";
|
||||
import { encryption } from "../../utils/fun";
|
||||
import { getEmailIfBind } from "../../api/personalCenter";
|
||||
|
||||
import { Debounce,throttle }from "../../utils/publicMethods";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -419,6 +419,10 @@ export default {
|
||||
type: "success",
|
||||
showClose: true,
|
||||
});
|
||||
for (const key in this.loginForm) {//清空表单
|
||||
this.loginForm[key] = "";
|
||||
}
|
||||
|
||||
this.$router.push(`/${this.lang}/login`);
|
||||
}
|
||||
},
|
||||
@@ -521,7 +525,8 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
submitForm() {
|
||||
|
||||
submitForm:Debounce(function(){
|
||||
this.$refs.ruleForm.validate((valid) => {
|
||||
if (valid) {
|
||||
//去空格
|
||||
@@ -596,7 +601,83 @@ export default {
|
||||
this.fetchResetPwd(form);
|
||||
}
|
||||
});
|
||||
},
|
||||
},200),
|
||||
// submitForm() {
|
||||
// this.$refs.ruleForm.validate((valid) => {
|
||||
// if (valid) {
|
||||
// //去空格
|
||||
// this.loginForm.userName = this.loginForm.email.trim();
|
||||
// this.loginForm.password = this.loginForm.password.trim();
|
||||
// this.loginForm.newPassword = this.loginForm.newPassword.trim();
|
||||
// if (this.loginForm.password !== this.loginForm.newPassword) {
|
||||
// this.$message({
|
||||
// message: this.$t(`user.confirmPassword2`),
|
||||
// type: "error",
|
||||
// customClass: "messageClass",
|
||||
// showClose: true,
|
||||
// });
|
||||
|
||||
// return;
|
||||
// }
|
||||
// //邮箱格式验证
|
||||
// const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/;
|
||||
|
||||
// let isMailbox = emailRegex.test(this.loginForm.email);
|
||||
// if (!isMailbox) {
|
||||
// this.$message({
|
||||
// message: this.$t(`user.emailVerification`),
|
||||
// type: "error",
|
||||
// customClass: "messageClass",
|
||||
// showClose: true,
|
||||
// });
|
||||
|
||||
// return;
|
||||
|
||||
// //用户名规则1.长度限制:3<=用户名<=16; 字符限制:仅允许使用字母、数字、下划线 用户名必须以字母开头
|
||||
// // const regex = /^[a-zA-Z][a-zA-Z0-9_]{2,15}$/; // 正则表达式
|
||||
// // const isValid = regex.test(this.loginForm.email);
|
||||
// // if (!isValid) {
|
||||
// // // 如果输入不符合要求,可以根据具体需求给出错误提示或进行其他处理
|
||||
// // this.$message({
|
||||
// // message: this.$t(`user.accountReminder`),
|
||||
// // type: "error",
|
||||
// // customClass: "messageClass",
|
||||
// // showClose: true
|
||||
// // });
|
||||
|
||||
// // return;
|
||||
// // }
|
||||
// }
|
||||
|
||||
// // 密码验证 8<=密码<=32 包含大小写字母、数字和特殊字符(!@#¥%……&*)
|
||||
// const regexPassword =
|
||||
// /^(?!.*[\u4e00-\u9fa5])(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_]+$)(?![a-z0-9]+$)(?![a-z\W_]+$)(?![0-9\W_]+$)[a-zA-Z0-9\W_]{8,32}$/; // 正则表达式
|
||||
// const PasswordIsValid = regexPassword.test(this.loginForm.password);
|
||||
// if (!PasswordIsValid) {
|
||||
// // 如果输入不符合要求,可以根据具体需求给出错误提示或进行其他处理
|
||||
// this.$message({
|
||||
// message: this.$t(`user.PasswordReminder`),
|
||||
// type: "error",
|
||||
// showClose: true,
|
||||
// });
|
||||
|
||||
// return;
|
||||
// }
|
||||
// // ,gCode: this.loginForm.gCode,
|
||||
// let obj = {
|
||||
// email: this.loginForm.email,
|
||||
// password: this.loginForm.password,
|
||||
// resetPwdCode: this.loginForm.resetPwdCode,
|
||||
// };
|
||||
// //加密
|
||||
// // const form = { ...this.loginForm };
|
||||
// // form.password = encryption(this.loginForm.password);
|
||||
// const form = { ...obj };
|
||||
// form.password = encryption(obj.password);
|
||||
// this.fetchResetPwd(form);
|
||||
// }
|
||||
// });
|
||||
// },
|
||||
handleClick() {
|
||||
this.$router.push(`/${this.lang}`);
|
||||
},
|
||||
|
||||
@@ -103,11 +103,21 @@ export default {
|
||||
data: this.FormDatas,
|
||||
}).then(res => {
|
||||
console.log(res,"文件返回");
|
||||
if (res.status == 200 && res.data.code != 200) {
|
||||
this.$message.error(res.data.msg);
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.ruleForm.files = res.data.data.id
|
||||
// if (this.ruleForm.files) {//成功拿到返回ID
|
||||
// this.fetchSubmitWork(this.ruleForm)
|
||||
// }
|
||||
if (this.ruleForm.files) {//成功拿到返回ID
|
||||
this.fetchSubmitWork(this.ruleForm)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
} else {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user