更新添加注销账户功能

This commit is contained in:
2026-01-08 13:58:29 +08:00
parent 382719404d
commit 9869ec0106
13 changed files with 334 additions and 75 deletions

View File

@@ -1,7 +1,8 @@
<template>
<div id="app">
<router-view class="page" />
<ChatWidget v-if="!$route.path.includes('/customerService') && !$isMobile && jurisdiction.roleKey !== 'back_admin'" />
<ChatWidget v-if="!$route.path.includes('/customerService') && !$isMobile && jurisdiction.roleKey !== 'back_admin'" />
</div>
</template>
<script >

View File

@@ -83,4 +83,24 @@ export function getUserProfile() {
method: 'get',
})
}
//获取注销账户验证码
export function sendCloseAccount(data) {
return request({
url: `auth/sendCloseAccount`,
method: 'post',
data
})
}
//注销账户
export function closeAccount(data) {
return request({
url: `auth/closeAccount`,
method: 'post',
data
})
}

View File

@@ -134,7 +134,9 @@ export const personalCenter_zh = {
ipFormat:"请检查IP地址格式是否正确",
screen:"筛选币种",
workOrderRecord:"工单记录",
deleteAccountWarning:"删除后关于此账户的相关信息将不能恢复,请慎重操作!",
deleteAccountSuccess:"账户删除成功",
}
}
@@ -243,5 +245,7 @@ export const personalCenter_en = {
ipFormat:"Please check if the IP address format is correct",
screen:"Filter currencies",
workOrderRecord:"Work order record",
deleteAccountWarning:"After deletion, the relevant information about this account cannot be restored. Please proceed with caution!",
deleteAccountSuccess:"Account deleted successfully",
}
}

View File

@@ -1,6 +1,6 @@
import { getIfBind, getBindInfo, getBindGoogle, getBindCode, getCloseStepTwo, getCloseCode, getUpdatePwd, getUpdatePwdCode } from "../../../api/personalCenter"
import { encryption } from "../../../utils/fun";
import { getResetPwd, getResetPwdCode } from "../../../api/login"
import { getResetPwd, getResetPwdCode, sendCloseAccount, closeAccount } from "../../../api/login"
export default {
data() {
return {
@@ -97,6 +97,18 @@ export default {
countDownTimePassword: 60,
timerPassword: null,
lang:"zh",
// 删除账户相关
deleteAccountParams: {
eCode: "",
gCode: "",
},
btnDisabledDeleteAccount: false,
bthTextDeleteAccount: "user.obtainVerificationCode",
countDownTimeDeleteAccount: 60,
timerDeleteAccount: null,
deleteAccountLoading: false,
deleteAccountCodeLoading: false, // 获取验证码按钮loading状态
userEmail: "",
}
},
computed: {
@@ -150,6 +162,13 @@ export default {
this.bthTextPassword = `user.again`
}
if (window.sessionStorage.getItem("deleteAccount_time")) {
this.countDownTimeDeleteAccount = Number(window.sessionStorage.getItem("deleteAccount_time"));
this.startCountDownDeleteAccount()
this.btnDisabledDeleteAccount = true;
this.bthTextDeleteAccount = `user.again`
}
},
mounted() {
@@ -159,6 +178,8 @@ export default {
if (this.$route.params.active) {
this.handelVerification()
}
// 获取用户邮箱
this.getUserEmail();
},
methods: {
async fetchIfBind(params) {
@@ -311,9 +332,166 @@ export default {
this.maintainDialogVisible = true
},
/**
* 获取用户邮箱
*/
getUserEmail() {
try {
const emailData = localStorage.getItem("userEmail");
if (emailData) {
const emailObj = JSON.parse(emailData);
// 如果是对象,尝试取常见的邮箱字段
this.userEmail = emailObj.email || emailObj.value || emailObj.userEmail || emailObj;
// 如果最终结果不是字符串,可能数据有问题
if (typeof this.userEmail !== "string") {
this.userEmail = "";
}
}
} catch (e) {
console.error("获取用户邮箱失败:", e);
this.userEmail = "";
}
},
/**
* 打开删除账户弹窗
*/
deleteAccount() {
this.getUserEmail(); // 确保获取最新邮箱
this.deleteAccountDialog = true
},
/**
* 获取删除账户验证码
*/
async handelDeleteAccountCode() {
if (!this.userEmail) {
this.$message({
showClose: true,
message: this.$t(`personal.mailbox`) + this.$t(`personal.pleaseEnter`),
type: 'error'
});
return;
}
this.deleteAccountCodeLoading = true;
try {
const data = await sendCloseAccount({ account: this.userEmail });
if (data && data.code === 200) {
this.$message({
message: this.$t(`user.codeSuccess`),
type: "success",
showClose: true
});
// 成功后开始倒计时
if (window.sessionStorage.getItem("deleteAccount_time") == null) {
this.startCountDownDeleteAccount()
} else {
this.countDownTimeDeleteAccount = Number(window.sessionStorage.getItem("deleteAccount_time"));
this.startCountDownDeleteAccount()
}
}
} catch (error) {
console.error("获取删除账户验证码失败:", error);
this.$message({
message: this.$t(`user.codeFailed`) || '获取验证码失败',
type: "error",
showClose: true
});
} finally {
this.deleteAccountCodeLoading = false;
}
},
/**
* 删除账户验证码倒计时
*/
startCountDownDeleteAccount() {
this.timerDeleteAccount = setInterval(() => {
if (this.countDownTimeDeleteAccount <= 1) {
clearInterval(this.timerDeleteAccount);
sessionStorage.removeItem("deleteAccount_time");
this.countDownTimeDeleteAccount = 60
this.btnDisabledDeleteAccount = false;
this.bthTextDeleteAccount = `user.obtainVerificationCode`
} else if (this.countDownTimeDeleteAccount > 0) {
this.countDownTimeDeleteAccount--;
this.btnDisabledDeleteAccount = true;
this.bthTextDeleteAccount = `user.again`
window.sessionStorage.setItem("deleteAccount_time", this.countDownTimeDeleteAccount);
}
}, 1000);
},
/**
* 确认删除账户
*/
confirmDeleteAccount() {
if (!this.deleteAccountParams.eCode) {
this.$message({
showClose: true,
message: this.$t(`personal.eCode`),
type: 'error'
});
return
}
if (!this.deleteAccountParams.gCode) {
this.$message({
showClose: true,
message: this.$t(`personal.gCode`),
type: 'error'
});
return
}
// 二次确认
this.$confirm(
this.$t(`personal.deleteAccountWarning`) || '删除后关于此账户的相关信息将不能恢复,请慎重操作!',
this.$t(`personal.Tips`) || '提示',
{
confirmButtonText: this.$t(`personal.determine`) || '确定',
cancelButtonText: this.$t(`personal.Cancel`) || '取消',
type: 'warning'
}
).then(() => {
this.submitDeleteAccount();
}).catch(() => {
// 用户取消
});
},
/**
* 提交删除账户请求
*/
async submitDeleteAccount() {
this.setLoading('deleteAccountLoading', true);
try {
const data = await closeAccount({
userEmail: this.userEmail,
eCode: this.deleteAccountParams.eCode,
gCode: this.deleteAccountParams.gCode
});
if (data && data.code === 200) {
this.$message({
message: this.$t(`personal.deleteAccountSuccess`) || '账户删除成功',
type: "success",
showClose: true
});
this.deleteAccountDialog = false;
// 清除本地存储并跳转到登录页
localStorage.removeItem("token");
localStorage.removeItem("userEmail");
const lang = this.$i18n.locale;
this.$router.push(`/${lang}/login`);
}
} catch (error) {
console.error("删除账户失败:", error);
}
this.setLoading('deleteAccountLoading', false);
},
/**
* 关闭删除账户弹窗
*/
closeDeleteAccountDialog() {
// 重置表单
this.deleteAccountParams.eCode = "";
this.deleteAccountParams.gCode = "";
},
handelVerification() {
// this.verificationDialogVisible = true
this.fetchBindInfo()

View File

@@ -62,6 +62,23 @@
</div>
</div>
<div class="itemBox">
<div class="left">
<div>
<img src="../../../assets/img/deleteUser.png" alt="deleteUser" loading="lazy"/>
</div>
<div class="text">
<p>{{ $t(`personal.deleteAccount`) }}</p>
<p>{{ $t(`personal.deleteDescription`) }}</p>
</div>
</div>
<div class="right">
<span class="modify" @click="deleteAccount">{{
$t(`personal.delete`)
}}</span>
</div>
</div>
</section>
@@ -128,37 +145,18 @@
>
</div>
</li>
<!-- <li >
<div class="topOneLeft">
<img src="../../../assets/img/maintain.png" alt="">
<div class="text">
<span style="font-size: 1.1em;">{{$t(`personal.maintainPassword`)}}</span>
<span style="color: rgba(0,0,0,0.5);">{{$t(`personal.maintenanceInstructions`)}}</span>
</div>
</div>
<div class="topOneRight2">
<el-button class="notEnabled">{{$t(`personal.notEnabled`)}}</el-button>
<span class="line"></span>
<span class="modify" @click="maintainPassword">{{$t(`personal.Open`)}}</span>
</div>
</li> -->
<!-- <li >
<div class="topOneLeft">
<img src="../../../assets/img/deleteUser.png" alt="">
<div class="text">
<span style="font-size: 1.1em;">{{$t(`personal.deleteAccount`)}}</span>
<span style="color: rgba(0,0,0,0.5);">{{$t(`personal.deleteDescription`)}}</span>
</div>
</div>
<div class="topOneRight">
<span class="modifyDelete" @click="deleteAccount"> <span class="bth"> {{$t(`personal.delete`)}}</span></span>
</div>
</li> -->
<li>
<div class="topOneLeft">
<img src="../../../assets/img/deleteUser.png" alt="deleteUser" loading="lazy"/>
<div class="text">
<span style="font-size: 1.1em;">{{$t(`personal.deleteAccount`)}}</span>
<span style="color: rgba(0,0,0,0.5);">{{$t(`personal.deleteDescription`)}}</span>
</div>
</div>
<div class="topOneRight delete-btn">
<span class="modify" id="deleteBtn" @click="deleteAccount">{{$t(`personal.delete`)}}</span>
</div>
</li>
</ul>
</section>
</section>
@@ -439,49 +437,62 @@
</section>
</el-dialog>
<!-- 删除账户 -->
<el-dialog :visible.sync="deleteAccountDialog" width="35%">
<section class="dialogBox2">
<el-dialog
:visible.sync="deleteAccountDialog"
width="40%"
:close-on-click-modal="false"
@close="closeDeleteAccountDialog"
>
<section class="verificationBox">
<div class="title">{{ $t(`personal.deleteAccount`) }}</div>
<div
class="deleteClauseBox"
v-for="item in clauseList"
:key="item.title"
>
<h3>{{ item.title }}</h3>
<ul>
<li v-for="subItem in item.children" :key="subItem.label">
{{ subItem.label }}
</li>
</ul>
<div class="inputBox">
<div class="inputItem">
<span class="title">{{ $t(`personal.mailbox`) }}</span>
<el-input
class="input"
:value="userEmail"
disabled
></el-input>
</div>
<div class="inputItem">
<span class="title">{{ $t(`personal.verificationCode`) }}</span>
<div class="verificationCode">
<el-input
type="text"
v-model="deleteAccountParams.eCode"
autocomplete="off"
:placeholder="$t(`user.verificationCode`)"
></el-input>
<el-button
class="codeBtn deleteAccountCodeBtn"
:disabled="btnDisabledDeleteAccount"
:loading="deleteAccountCodeLoading"
@click="handelDeleteAccountCode"
>
<span
v-if="countDownTimeDeleteAccount < 60 && countDownTimeDeleteAccount > 0"
>{{ countDownTimeDeleteAccount }}</span
>{{ $t(bthTextDeleteAccount) }}</el-button
>
</div>
</div>
<div class="inputItem">
<span class="title">{{ $t(`personal.oneTimePassword`) }}</span>
<el-input
class="input"
type="number"
v-model="deleteAccountParams.gCode"
placeholder="000000"
></el-input>
</div>
</div>
<div class="dashedLine"></div>
<div>
<p>{{ $t(`personal.reasonForDeletion`) }}</p>
<el-select
v-model="value"
:placeholder="$t(`personal.select`)"
class="select"
>
<el-option
v-for="item in reasonList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
<div class="bthBox">
<div class="verificationBthBox deleteAccountBtnBox">
<el-button
style="width: 40%; font-size: 1.1em; margin-top: 30px"
@click="deleteAccountDialog = false"
>{{ $t(`personal.Cancel`) }}</el-button
>
<el-button
style="width: 40%; font-size: 1.1em; margin-top: 30px"
type="primary"
@click="deleteAccountDialog = false"
>{{ $t(`personal.determine`) }}</el-button
style=" margin: 0 auto"
:loading="deleteAccountLoading"
class="confirmBtn"
@click="confirmDeleteAccount"
>{{ $t(`personal.delete`) }}</el-button
>
</div>
</section>
@@ -550,6 +561,11 @@ export default {
border-radius: 5px;
margin-left: 10px;
}
.delete-btn {
background: #661fff;
color: #fff;
border: none;
}
}
.right2{
@@ -809,6 +825,11 @@ export default {
padding: 6px 18px;
border-radius: 5px;
}
.delete-btn {
background: #661fff;
color: #fff;
border: none;
}
.modifyDelete {
display: inline-block;
width: 90%;
@@ -856,6 +877,18 @@ export default {
}
}
}
.delete-btn{
display: flex;
align-items: right !important;
// background: palevioletred;
justify-content: right !important;
padding-right: 3px;
#deleteBtn{
// background: palevioletred;
padding: 7px 18px;
}
}
}
}
@@ -1109,6 +1142,19 @@ export default {
font-size: 13px;
margin-left: 2px;
}
// 删除账户获取验证码按钮样式
.deleteAccountCodeBtn {
background: #661fff;
color: #fff;
border: none;
&:hover {
background: #5518e6;
}
&:disabled {
background: #ccc;
color: #fff;
}
}
}
.bthBox {
width: 100%;
@@ -1136,6 +1182,10 @@ export default {
color: #fff;
border: none;
}
// 删除账户按钮更长
.deleteAccountBtnBox .el-button.confirmBtn {
min-width: 70% !important;
}
}
}

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><meta name=google-site-verification content=pKAZogQ0NQ6L4j9-V58WJMjm7zYCFwkJXSJzWu9UDM8><meta name=robots content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"><meta name=googlebot content="index, follow"><meta name=googlebot-news content="index, follow"><meta name=bingbot content="index, follow"><link rel=alternate hreflang=zh href=https://m2pool.com/zh><link rel=alternate hreflang=en href=https://m2pool.com/en><link rel=alternate hreflang=x-default href=https://m2pool.com/en><meta property=og:title content="M2pool - Stable leading high-yield mining pool"><meta property=og:description content="M2Pool provides professional mining services, supporting multiple cryptocurrency mining"><meta property=og:url content=https://m2pool.com/en><meta property=og:site_name content=M2Pool><meta property=og:type content=website><meta property=og:image content=https://m2pool.com/logo.png><link rel=icon href=/favicon.ico><link rel=stylesheet href=//at.alicdn.com/t/c/font_4582735_7i8wfzc0art.css><title>M2pool - Stable leading high-yield mining pool</title><meta name=keywords content="M2Pool, cryptocurrency mining pool,entropyx, 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"><script defer=defer src=/js/chunk-vendors-c0d76f48.f34181ba.js></script><script defer=defer src=/js/chunk-vendors-bc050c32.8062ab74.js></script><script defer=defer src=/js/chunk-vendors-3003db77.d0b93d36.js></script><script defer=defer src=/js/chunk-vendors-9d134daf.bb668c99.js></script><script defer=defer src=/js/chunk-vendors-96cecd74.a7d9b845.js></script><script defer=defer src=/js/chunk-vendors-c2f7d60e.3710fdc2.js></script><script defer=defer src=/js/chunk-vendors-89d5c698.2190b4ca.js></script><script defer=defer src=/js/chunk-vendors-377fed06.0e89b4b7.js></script><script defer=defer src=/js/chunk-vendors-c9ff040c.57bd8c18.js></script><script defer=defer src=/js/app-42f9d7e6.22250631.js></script><script defer=defer src=/js/app-5c551db8.946f1024.js></script><script defer=defer src=/js/app-45954fd3.1331a09e.js></script><script defer=defer src=/js/app-72600b29.42f2b75e.js></script><script defer=defer src=/js/app-5a0d40dd.f3cdcc6c.js></script><script defer=defer src=/js/app-113c6c50.31c63edf.js></script><link href=/css/chunk-vendors-bc050c32.6f97509c.css rel=stylesheet><link href=/css/app-189e7968.aa4fb95c.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, 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"><script defer=defer src=/js/chunk-vendors-c0d76f48.f34181ba.js></script><script defer=defer src=/js/chunk-vendors-bc050c32.8062ab74.js></script><script defer=defer src=/js/chunk-vendors-3003db77.d0b93d36.js></script><script defer=defer src=/js/chunk-vendors-9d134daf.bb668c99.js></script><script defer=defer src=/js/chunk-vendors-96cecd74.a7d9b845.js></script><script defer=defer src=/js/chunk-vendors-c2f7d60e.3710fdc2.js></script><script defer=defer src=/js/chunk-vendors-89d5c698.2190b4ca.js></script><script defer=defer src=/js/chunk-vendors-377fed06.0e89b4b7.js></script><script defer=defer src=/js/chunk-vendors-c9ff040c.57bd8c18.js></script><script defer=defer src=/js/app-42f9d7e6.11a01d0a.js></script><script defer=defer src=/js/app-5c551db8.3726e21e.js></script><script defer=defer src=/js/app-45954fd3.1331a09e.js></script><script defer=defer src=/js/app-72600b29.ead62671.js></script><script defer=defer src=/js/app-5a0d40dd.b726f201.js></script><script defer=defer src=/js/app-113c6c50.ede228a3.js></script><link href=/css/chunk-vendors-bc050c32.6f97509c.css rel=stylesheet><link href=/css/app-189e7968.ecff2d4d.css rel=stylesheet></head><body><div id=app></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long