279 lines
8.3 KiB
Vue
279 lines
8.3 KiB
Vue
|
|
<script setup>
|
|||
|
|
import { storeToRefs } from 'pinia'
|
|||
|
|
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|||
|
|
import { showConfirmDialog, showToast } from 'vant'
|
|||
|
|
import AccountCancelAgreement from '@/views/AccountCancelAgreement.vue'
|
|||
|
|
import useApiFetch from '@/composables/useApiFetch'
|
|||
|
|
import { useAgentStore } from '@/stores/agentStore'
|
|||
|
|
import { useUserStore } from '@/stores/userStore'
|
|||
|
|
|
|||
|
|
const router = useRouter()
|
|||
|
|
|
|||
|
|
const userStore = useUserStore()
|
|||
|
|
const agentStore = useAgentStore()
|
|||
|
|
const { mobile } = storeToRefs(userStore)
|
|||
|
|
const { isAgent, level } = storeToRefs(agentStore)
|
|||
|
|
|
|||
|
|
const loading = ref(true)
|
|||
|
|
const revenueData = ref(null)
|
|||
|
|
|
|||
|
|
const showSmsModal = ref(false)
|
|||
|
|
const cancelAccountCode = ref('')
|
|||
|
|
const cancelSmsCountdown = ref(0)
|
|||
|
|
let cancelSmsTimer = null
|
|||
|
|
|
|||
|
|
function maskName(name) {
|
|||
|
|
if (!name || name.length < 11)
|
|||
|
|
return name
|
|||
|
|
return `${name.substring(0, 3)}****${name.substring(7)}`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const hasWalletBalance = computed(() => {
|
|||
|
|
const b = Number(revenueData.value?.balance ?? 0)
|
|||
|
|
const f = Number(revenueData.value?.frozen_balance ?? 0)
|
|||
|
|
return b > 0 || f > 0
|
|||
|
|
})
|
|||
|
|
const showBalanceWarning = computed(() => isAgent.value && hasWalletBalance.value)
|
|||
|
|
|
|||
|
|
const showVipLevelReminder = computed(() =>
|
|||
|
|
isAgent.value && (level.value === 'VIP' || level.value === 'SVIP'),
|
|||
|
|
)
|
|||
|
|
const vipLevelLabel = computed(() => (level.value === 'SVIP' ? 'SVIP' : 'VIP'))
|
|||
|
|
|
|||
|
|
const showAnyReminder = computed(() => showBalanceWarning.value || showVipLevelReminder.value)
|
|||
|
|
|
|||
|
|
onMounted(async () => {
|
|||
|
|
await userStore.fetchUserInfo()
|
|||
|
|
if (!userStore.mobile) {
|
|||
|
|
loading.value = false
|
|||
|
|
showToast('请先绑定手机号')
|
|||
|
|
setTimeout(() => router.back(), 1500)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
await agentStore.fetchAgentStatus()
|
|||
|
|
if (agentStore.isAgent) {
|
|||
|
|
const { data, error } = await useApiFetch('/agent/revenue').get().json()
|
|||
|
|
if (!error.value && data.value?.code === 200)
|
|||
|
|
revenueData.value = data.value.data
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch {
|
|||
|
|
/* ignore */
|
|||
|
|
}
|
|||
|
|
finally {
|
|||
|
|
loading.value = false
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
function onExit() {
|
|||
|
|
router.back()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function startCancelSmsCountdown() {
|
|||
|
|
cancelSmsCountdown.value = 60
|
|||
|
|
if (cancelSmsTimer)
|
|||
|
|
clearInterval(cancelSmsTimer)
|
|||
|
|
cancelSmsTimer = setInterval(() => {
|
|||
|
|
if (cancelSmsCountdown.value > 0)
|
|||
|
|
cancelSmsCountdown.value--
|
|||
|
|
else
|
|||
|
|
clearInterval(cancelSmsTimer)
|
|||
|
|
}, 1000)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onUnmounted(() => {
|
|||
|
|
if (cancelSmsTimer)
|
|||
|
|
clearInterval(cancelSmsTimer)
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
function openSmsModal() {
|
|||
|
|
cancelAccountCode.value = ''
|
|||
|
|
showSmsModal.value = true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function onConfirmTap() {
|
|||
|
|
if (showBalanceWarning.value) {
|
|||
|
|
showConfirmDialog({
|
|||
|
|
title: '确认注销',
|
|||
|
|
message: '您的代理账户仍有余额或待结账金额,注销后将无法通过本账号提现,确定继续注销?',
|
|||
|
|
confirmButtonText: '继续',
|
|||
|
|
cancelButtonText: '取消',
|
|||
|
|
})
|
|||
|
|
.then(() => openSmsModal())
|
|||
|
|
.catch(() => {})
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
openSmsModal()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function closeSmsModal() {
|
|||
|
|
showSmsModal.value = false
|
|||
|
|
cancelAccountCode.value = ''
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function sendCancelAccountSms() {
|
|||
|
|
if (!mobile.value) {
|
|||
|
|
showToast('请先绑定手机号')
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
if (cancelSmsCountdown.value > 0)
|
|||
|
|
return
|
|||
|
|
const { data, error } = await useApiFetch('/auth/sendSms')
|
|||
|
|
.post({ mobile: mobile.value, actionType: 'cancelAccount', captchaVerifyParam: '' })
|
|||
|
|
.json()
|
|||
|
|
if (!error.value && data.value?.code === 200) {
|
|||
|
|
showToast({ message: '验证码已发送' })
|
|||
|
|
startCancelSmsCountdown()
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
showToast({ message: data.value?.msg || '发送失败' })
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function clearAuthAndGoHome() {
|
|||
|
|
localStorage.removeItem('token')
|
|||
|
|
localStorage.removeItem('refreshAfter')
|
|||
|
|
localStorage.removeItem('accessExpire')
|
|||
|
|
localStorage.removeItem('userInfo')
|
|||
|
|
localStorage.removeItem('agentInfo')
|
|||
|
|
userStore.resetUser()
|
|||
|
|
agentStore.resetAgent()
|
|||
|
|
window.location.href = '/'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function submitCancelAccount() {
|
|||
|
|
if (cancelAccountCode.value.length !== 6) {
|
|||
|
|
showToast('请输入6位验证码')
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
const { data, error } = await useApiFetch('/user/cancelOut')
|
|||
|
|
.post({ code: cancelAccountCode.value })
|
|||
|
|
.json()
|
|||
|
|
if (!error.value && data.value?.code === 200) {
|
|||
|
|
showToast({ message: '账号已注销' })
|
|||
|
|
closeSmsModal()
|
|||
|
|
clearAuthAndGoHome()
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
showToast({ message: data.value?.msg || '注销失败' })
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<!-- 减导航栏占位高度,避免整页超出视口(与 PageLayout 的 van-nav-bar placeholder 配合) -->
|
|||
|
|
<div
|
|||
|
|
class="box-border flex flex-col bg-gray-50"
|
|||
|
|
style="min-height: calc(100vh - var(--van-nav-bar-height, 46px)); height: calc(100vh - var(--van-nav-bar-height, 46px));"
|
|||
|
|
>
|
|||
|
|
<div v-if="loading" class="flex flex-1 items-center justify-center py-20 text-gray-500">
|
|||
|
|
加载中...
|
|||
|
|
</div>
|
|||
|
|
<template v-else>
|
|||
|
|
<div class="flex min-h-0 min-w-0 flex-1 flex-col">
|
|||
|
|
<div class="min-h-0 flex-1 overflow-y-auto border-b border-gray-100 bg-white">
|
|||
|
|
<AccountCancelAgreement />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div
|
|||
|
|
v-if="showAnyReminder"
|
|||
|
|
class="flex-shrink-0 space-y-2 border-t border-gray-100 bg-gray-50 px-4 py-3"
|
|||
|
|
>
|
|||
|
|
<div
|
|||
|
|
v-if="showBalanceWarning"
|
|||
|
|
class="rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900"
|
|||
|
|
>
|
|||
|
|
<p class="font-medium">
|
|||
|
|
钱包提示
|
|||
|
|
</p>
|
|||
|
|
<p class="mt-1 leading-relaxed">
|
|||
|
|
检测到您为代理且账户仍有余额(¥{{ (revenueData?.balance ?? 0).toFixed(2) }})或待结账金额(¥{{ (revenueData?.frozen_balance ?? 0).toFixed(2) }})。注销后将无法通过本账号提现,请确认已了解风险。
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<div
|
|||
|
|
v-if="showVipLevelReminder"
|
|||
|
|
class="rounded-lg border border-violet-200 bg-violet-50 p-3 text-sm text-violet-900"
|
|||
|
|
>
|
|||
|
|
<p class="font-medium">
|
|||
|
|
会员提示
|
|||
|
|
</p>
|
|||
|
|
<p class="mt-1 leading-relaxed">
|
|||
|
|
您当前为 {{ vipLevelLabel }} 代理会员,注销后该账号下的代理身份与相关权益将按平台规则终止,请确认已了解风险。
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="flex-shrink-0 border-t border-gray-200 bg-gray-50 px-4 pb-[max(1rem,env(safe-area-inset-bottom))] pt-3">
|
|||
|
|
<div class="flex gap-3">
|
|||
|
|
<button
|
|||
|
|
type="button"
|
|||
|
|
class="flex-1 rounded-lg border border-gray-300 bg-white py-3 text-gray-800"
|
|||
|
|
@click="onExit"
|
|||
|
|
>
|
|||
|
|
退出
|
|||
|
|
</button>
|
|||
|
|
<button
|
|||
|
|
type="button"
|
|||
|
|
class="flex-1 rounded-lg bg-red-500 py-3 text-white"
|
|||
|
|
@click="onConfirmTap"
|
|||
|
|
>
|
|||
|
|
确认
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<div
|
|||
|
|
v-if="showSmsModal"
|
|||
|
|
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4"
|
|||
|
|
@click.self="closeSmsModal"
|
|||
|
|
>
|
|||
|
|
<div class="w-full max-w-sm rounded-xl bg-white p-5 shadow-lg" @click.stop>
|
|||
|
|
<p class="mb-2 text-base font-medium text-gray-800">
|
|||
|
|
验证手机号
|
|||
|
|
</p>
|
|||
|
|
<p class="mb-4 text-sm text-gray-500">
|
|||
|
|
将向 {{ maskName(mobile) }} 发送验证码。
|
|||
|
|
</p>
|
|||
|
|
<input
|
|||
|
|
v-model="cancelAccountCode"
|
|||
|
|
type="text"
|
|||
|
|
maxlength="6"
|
|||
|
|
inputmode="numeric"
|
|||
|
|
placeholder="请输入6位验证码"
|
|||
|
|
class="mb-4 w-full rounded-lg border border-gray-200 px-3 py-2 text-base"
|
|||
|
|
>
|
|||
|
|
<div class="mb-4">
|
|||
|
|
<button
|
|||
|
|
type="button"
|
|||
|
|
class="w-full rounded-lg bg-gray-100 py-2 text-sm text-gray-700 disabled:opacity-50"
|
|||
|
|
:disabled="cancelSmsCountdown > 0"
|
|||
|
|
@click="sendCancelAccountSms"
|
|||
|
|
>
|
|||
|
|
{{ cancelSmsCountdown > 0 ? `${cancelSmsCountdown}s` : '获取验证码' }}
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
<div class="flex gap-2">
|
|||
|
|
<button
|
|||
|
|
type="button"
|
|||
|
|
class="flex-1 rounded-lg bg-gray-200 py-2 text-gray-800"
|
|||
|
|
@click="closeSmsModal"
|
|||
|
|
>
|
|||
|
|
取消
|
|||
|
|
</button>
|
|||
|
|
<button
|
|||
|
|
type="button"
|
|||
|
|
class="flex-1 rounded-lg bg-red-500 py-2 text-white"
|
|||
|
|
@click="submitCancelAccount"
|
|||
|
|
>
|
|||
|
|
确认注销
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|