fix: 新增账号注销功能
This commit is contained in:
parent
90c0f85972
commit
58f16be457
@ -5,6 +5,11 @@ export default {
|
|||||||
getUserInfo: () => request.get('/base/userinfo'),
|
getUserInfo: () => request.get('/base/userinfo'),
|
||||||
getUserMenu: () => request.get('/base/usermenu'),
|
getUserMenu: () => request.get('/base/usermenu'),
|
||||||
getUserApi: () => request.get('/base/userapi'),
|
getUserApi: () => request.get('/base/userapi'),
|
||||||
|
deleteAccount: (data) => request.delete('/app-user/account', {
|
||||||
|
data: {
|
||||||
|
code: data.code // Body 中携带 code
|
||||||
|
}
|
||||||
|
}),
|
||||||
// 手机号
|
// 手机号
|
||||||
registerPhone: (data) => request.post('/app-user/register', data, { noNeedToken: true }),
|
registerPhone: (data) => request.post('/app-user/register', data, { noNeedToken: true }),
|
||||||
loginPhone: (data) => request.post('/app-user/login', data, { noNeedToken: true }),
|
loginPhone: (data) => request.post('/app-user/login', data, { noNeedToken: true }),
|
||||||
|
|||||||
BIN
web1/src/assets/icon/iconLogout.png
Normal file
BIN
web1/src/assets/icon/iconLogout.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
web1/src/assets/icon/评估完成.png
Normal file
BIN
web1/src/assets/icon/评估完成.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@ -52,6 +52,14 @@ export const basicRoutes = [
|
|||||||
title: '抬头管理',
|
title: '抬头管理',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Logout',
|
||||||
|
path: 'logout',
|
||||||
|
component: () => import('@/views/user-center/components/Logout.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '账号注销',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,7 +2,17 @@
|
|||||||
<div class="pages">
|
<div class="pages">
|
||||||
<AppHeader class="page-header" />
|
<AppHeader class="page-header" />
|
||||||
<!-- 页面初始化 loading -->
|
<!-- 页面初始化 loading -->
|
||||||
<div v-if="pageLoading" class="right" style="display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center">
|
<div
|
||||||
|
v-if="pageLoading"
|
||||||
|
class="right"
|
||||||
|
style="
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
<n-spin size="large" />
|
<n-spin size="large" />
|
||||||
<div style="font-size: 16px; color: #999999; margin-top: 20px">加载中...</div>
|
<div style="font-size: 16px; color: #999999; margin-top: 20px">加载中...</div>
|
||||||
</div>
|
</div>
|
||||||
@ -305,7 +315,9 @@
|
|||||||
:default-file-list="modalForm.inheritor_certificates"
|
:default-file-list="modalForm.inheritor_certificates"
|
||||||
:max="uploadLimit"
|
:max="uploadLimit"
|
||||||
list-type="image-card"
|
list-type="image-card"
|
||||||
:on-before-upload="(options) => handleBeforeUpload(options, 'inheritor_certificates')"
|
:on-before-upload="
|
||||||
|
(options) => handleBeforeUpload(options, 'inheritor_certificates')
|
||||||
|
"
|
||||||
@finish="handleFinish3"
|
@finish="handleFinish3"
|
||||||
@remove="delete3"
|
@remove="delete3"
|
||||||
>
|
>
|
||||||
@ -569,35 +581,48 @@
|
|||||||
</n-tooltip>
|
</n-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<n-select
|
<div>
|
||||||
style="width: 330px"
|
<div style="display: flex">
|
||||||
v-model:value="modalForm.online_accounts[0]"
|
<n-select
|
||||||
placeholder="请选择"
|
style="width: 220px"
|
||||||
:options="accountsOptions"
|
v-model:value="modalForm.online_accounts[0]"
|
||||||
/>
|
placeholder="请选择"
|
||||||
<NInput
|
:options="accountsOptions"
|
||||||
v-model:value="modalForm.online_accounts[1]"
|
/>
|
||||||
placeholder="请输入账号"
|
<NInput
|
||||||
style="width: 220px; margin-left: 10px"
|
v-model:value="modalForm.online_accounts[1]"
|
||||||
/>
|
placeholder="请输入账号"
|
||||||
<NInput
|
style="width: 220px; margin-left: 10px"
|
||||||
v-model:value="modalForm.online_accounts[2]"
|
/>
|
||||||
placeholder="请输入点赞数量"
|
<NInput
|
||||||
style="width: 220px; margin-left: 10px"
|
v-model:value="modalForm.online_accounts[2]"
|
||||||
type="number"
|
placeholder="请输入点赞数量"
|
||||||
/>
|
style="width: 220px; margin-left: 10px"
|
||||||
<NInput
|
type="number"
|
||||||
v-model:value="modalForm.online_accounts[3]"
|
/>
|
||||||
placeholder="请输入评论数量"
|
</div>
|
||||||
style="width: 220px; margin-left: 10px"
|
|
||||||
type="number"
|
<div style="display: flex; margin-top: 12px">
|
||||||
/>
|
<NInput
|
||||||
<NInput
|
v-model:value="modalForm.online_accounts[3]"
|
||||||
v-model:value="modalForm.online_accounts[4]"
|
placeholder="请输入评论数量"
|
||||||
placeholder="请输入分享数量"
|
style="width: 220px"
|
||||||
style="width: 220px; margin-left: 10px"
|
type="number"
|
||||||
type="number"
|
/>
|
||||||
/>
|
<NInput
|
||||||
|
v-model:value="modalForm.online_accounts[4]"
|
||||||
|
placeholder="请输入分享数量"
|
||||||
|
style="width: 220px; margin-left: 10px"
|
||||||
|
type="number"
|
||||||
|
/>
|
||||||
|
<NInput
|
||||||
|
v-model:value="modalForm.online_accounts[5]"
|
||||||
|
placeholder="请输入近七天点击量"
|
||||||
|
style="width: 220px; margin-left: 10px"
|
||||||
|
type="number"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
<n-grid v-if="currentStep == 4" :cols="24" :x-gap="0">
|
<n-grid v-if="currentStep == 4" :cols="24" :x-gap="0">
|
||||||
@ -903,7 +928,17 @@
|
|||||||
重新评估
|
重新评估
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!pageLoading && status == 'pending'" class="right" style="display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center">
|
<div
|
||||||
|
v-if="!pageLoading && status == 'pending'"
|
||||||
|
class="right"
|
||||||
|
style="
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
class="loading-icon"
|
class="loading-icon"
|
||||||
style="width: 100px; height: 100px"
|
style="width: 100px; height: 100px"
|
||||||
@ -1168,7 +1203,7 @@ const modalRules = {
|
|||||||
required: true,
|
required: true,
|
||||||
message: '',
|
message: '',
|
||||||
trigger: ['input', 'blur'],
|
trigger: ['input', 'blur'],
|
||||||
len: 5,
|
len: 6,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@ -1195,6 +1230,11 @@ const modalRules = {
|
|||||||
message: '请输入账号分享量',
|
message: '请输入账号分享量',
|
||||||
trigger: ['input', 'blur'],
|
trigger: ['input', 'blur'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入近七天点击量',
|
||||||
|
trigger: ['input', 'blur'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -1544,6 +1584,7 @@ const submit = () => {
|
|||||||
likes: modalForm.online_accounts[2],
|
likes: modalForm.online_accounts[2],
|
||||||
comments: modalForm.online_accounts[3],
|
comments: modalForm.online_accounts[3],
|
||||||
shares: modalForm.online_accounts[4],
|
shares: modalForm.online_accounts[4],
|
||||||
|
views: modalForm.online_accounts[5],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if (modalForm.online_accounts[0] == '1') {
|
} else if (modalForm.online_accounts[0] == '1') {
|
||||||
@ -1553,6 +1594,7 @@ const submit = () => {
|
|||||||
likes: modalForm.online_accounts[2],
|
likes: modalForm.online_accounts[2],
|
||||||
comments: modalForm.online_accounts[3],
|
comments: modalForm.online_accounts[3],
|
||||||
shares: modalForm.online_accounts[4],
|
shares: modalForm.online_accounts[4],
|
||||||
|
views: modalForm.online_accounts[5],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if (modalForm.online_accounts[0] == '2') {
|
} else if (modalForm.online_accounts[0] == '2') {
|
||||||
@ -1562,6 +1604,7 @@ const submit = () => {
|
|||||||
likes: modalForm.online_accounts[2],
|
likes: modalForm.online_accounts[2],
|
||||||
comments: modalForm.online_accounts[3],
|
comments: modalForm.online_accounts[3],
|
||||||
shares: modalForm.online_accounts[4],
|
shares: modalForm.online_accounts[4],
|
||||||
|
views: modalForm.online_accounts[5],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if (modalForm.online_accounts[0] == '3') {
|
} else if (modalForm.online_accounts[0] == '3') {
|
||||||
@ -1571,6 +1614,7 @@ const submit = () => {
|
|||||||
likes: modalForm.online_accounts[2],
|
likes: modalForm.online_accounts[2],
|
||||||
comments: modalForm.online_accounts[3],
|
comments: modalForm.online_accounts[3],
|
||||||
shares: modalForm.online_accounts[4],
|
shares: modalForm.online_accounts[4],
|
||||||
|
views: modalForm.online_accounts[5],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1746,12 +1790,12 @@ onMounted(async () => {
|
|||||||
page: 1,
|
page: 1,
|
||||||
page_size: 99,
|
page_size: 99,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果有 id 参数,说明是从估值记录进入,需要显示 loading
|
// 如果有 id 参数,说明是从估值记录进入,需要显示 loading
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
pageLoading.value = true
|
pageLoading.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
await getHistoryList()
|
await getHistoryList()
|
||||||
|
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
|
|||||||
@ -185,11 +185,7 @@
|
|||||||
</n-form-item>
|
</n-form-item>
|
||||||
|
|
||||||
<div class="btn-container">
|
<div class="btn-container">
|
||||||
<button
|
<button class="primary-btn" :disabled="!isFormValid" @click="handleUploadSubmit">
|
||||||
class="primary-btn"
|
|
||||||
:disabled="!isFormValid"
|
|
||||||
@click="handleUploadSubmit"
|
|
||||||
>
|
|
||||||
确认上传
|
确认上传
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -295,11 +291,7 @@ const message = useMessage()
|
|||||||
|
|
||||||
// 计算表单是否有效
|
// 计算表单是否有效
|
||||||
const isFormValid = computed(() => {
|
const isFormValid = computed(() => {
|
||||||
return (
|
return uploadedFiles.value.length > 0 && !!formModel.invoiceHeader && !!formModel.invoiceType
|
||||||
uploadedFiles.value.length > 0 &&
|
|
||||||
!!formModel.invoiceHeader &&
|
|
||||||
!!formModel.invoiceType
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleUploadFinish = ({ file, event }) => {
|
const handleUploadFinish = ({ file, event }) => {
|
||||||
@ -384,10 +376,10 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title-bar {
|
.title-bar {
|
||||||
width: 4px;
|
width: 6px;
|
||||||
height: 16px;
|
height: 24px;
|
||||||
background: #a30113;
|
background: #a30113;
|
||||||
border-radius: 2px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-text {
|
.title-text {
|
||||||
|
|||||||
@ -315,10 +315,10 @@ const rowKey = (row) => row.id ?? row.name ?? row.company_name ?? row.taxId ?? r
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title-bar {
|
.title-bar {
|
||||||
width: 4px;
|
width: 6px;
|
||||||
height: 16px;
|
height: 24px;
|
||||||
background: #a30113;
|
background: #a30113;
|
||||||
border-radius: 2px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-text {
|
.title-text {
|
||||||
|
|||||||
368
web1/src/views/user-center/components/Logout.vue
Normal file
368
web1/src/views/user-center/components/Logout.vue
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="header-left">
|
||||||
|
<div class="title-bar"></div>
|
||||||
|
<div class="title-text">账号注销</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="deleteAble" class="logout-container">
|
||||||
|
<!-- 手机号信息 -->
|
||||||
|
<div class="phone-info">当前绑定的手机号码为:{{ maskedPhone }}</div>
|
||||||
|
|
||||||
|
<!-- 验证码输入区域 -->
|
||||||
|
<div class="code-form">
|
||||||
|
<n-form :model="form" :rules="rules" ref="formRef" label-width="100px">
|
||||||
|
<n-form-item label="" prop="code" class="verify-code-item">
|
||||||
|
<!-- 验证码输入框 + 按钮 容器 -->
|
||||||
|
<div class="code-input-wrapper">
|
||||||
|
<n-input
|
||||||
|
v-model:value="form.code"
|
||||||
|
placeholder="手机验证码"
|
||||||
|
maxlength="6"
|
||||||
|
@input="handleCodeInput"
|
||||||
|
class="custom-code-input"
|
||||||
|
:bordered="false"
|
||||||
|
/>
|
||||||
|
<n-button
|
||||||
|
class="send-code-btn"
|
||||||
|
text
|
||||||
|
@click="handleSendCode"
|
||||||
|
:disabled="countDown > 0"
|
||||||
|
>
|
||||||
|
{{ countDown > 0 ? `${countDown}s后重新获取` : '获取验证码' }}
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 注销按钮 -->
|
||||||
|
<n-button class="logout-btn" @click="handleLogout" :disabled="!isFormValid"> 确定 </n-button>
|
||||||
|
</div>
|
||||||
|
<div v-else class="logout-container" style="text-align: center">
|
||||||
|
<img src="@/assets/icon/评估完成.png" mode="scaleToFill" class="warn-icon" />
|
||||||
|
<p class="warn-title">无法注销</p>
|
||||||
|
<p class="warn-content">当前有未完成的估值记录/剩余估值次数,无法注销账号</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch, onUnmounted } from 'vue'
|
||||||
|
import { defineProps, defineEmits } from 'vue'
|
||||||
|
import { useMessage, useDialog } from 'naive-ui' // 引入 Naive UI 消息/弹窗
|
||||||
|
|
||||||
|
// 初始化 Naive UI 消息和弹窗
|
||||||
|
const message = useMessage()
|
||||||
|
const dialog = useDialog()
|
||||||
|
|
||||||
|
// 接收父组件传递的手机号
|
||||||
|
const props = defineProps({
|
||||||
|
userPhone: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
deleteAble: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义事件
|
||||||
|
const emits = defineEmits(['send-code', 'confirm-logout'])
|
||||||
|
|
||||||
|
// 表单引用
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const form = ref({
|
||||||
|
code: '',
|
||||||
|
})
|
||||||
|
// 倒计时
|
||||||
|
const countDown = ref(0)
|
||||||
|
let timer = null
|
||||||
|
|
||||||
|
// 手机号脱敏处理
|
||||||
|
const maskedPhone = computed(() => {
|
||||||
|
if (!props.userPhone) return ''
|
||||||
|
return `${props.userPhone.slice(0, 3)}****${props.userPhone.slice(7, 11)}`
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const rules = ref({
|
||||||
|
code: [
|
||||||
|
{ required: true, message: '请输入验证码', trigger: 'blur' },
|
||||||
|
{ len: 6, message: '请输入6位验证码', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表单是否有效
|
||||||
|
const isFormValid = computed(() => {
|
||||||
|
return props.userPhone && form.value.code.length === 6
|
||||||
|
})
|
||||||
|
|
||||||
|
// 验证码输入限制
|
||||||
|
const handleCodeInput = () => {
|
||||||
|
if (form.value.code.length > 6) {
|
||||||
|
form.value.code = form.value.code.slice(0, 6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送验证码
|
||||||
|
const handleSendCode = async () => {
|
||||||
|
if (!props.userPhone) {
|
||||||
|
message.warning('手机号不存在,无法发送验证码')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用父组件的发送验证码方法
|
||||||
|
const res = await emits('send-code', props.userPhone)
|
||||||
|
if (res) {
|
||||||
|
// 启动倒计时
|
||||||
|
countDown.value = 60
|
||||||
|
timer = setInterval(() => {
|
||||||
|
countDown.value--
|
||||||
|
if (countDown.value <= 0) {
|
||||||
|
clearInterval(timer)
|
||||||
|
timer = null
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
message.success('验证码发送成功')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交注销
|
||||||
|
const handleLogout = () => {
|
||||||
|
// 表单验证
|
||||||
|
formRef.value.validate((errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
emits('confirm-logout', {
|
||||||
|
code: form.value.code,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
message.warning('请填写正确的6位验证码')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面卸载时清除定时器
|
||||||
|
watch(
|
||||||
|
() => countDown.value,
|
||||||
|
(val) => {
|
||||||
|
if (val <= 0 && timer) {
|
||||||
|
clearInterval(timer)
|
||||||
|
timer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 组件卸载时清除定时器
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (timer) {
|
||||||
|
clearInterval(timer)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 根容器样式 */
|
||||||
|
.logout-container {
|
||||||
|
width: 600px;
|
||||||
|
margin: 50px auto;
|
||||||
|
padding: 30px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 标题样式 */
|
||||||
|
.logout-title {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #303133;
|
||||||
|
line-height: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 手机号信息样式 */
|
||||||
|
.phone-info {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单容器 */
|
||||||
|
.code-form {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
margin-top: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 验证码表单项 */
|
||||||
|
.verify-code-item {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 验证码输入框 + 按钮 容器(核心布局) */
|
||||||
|
.code-input-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 42px;
|
||||||
|
gap: 10px; /* 输入框和按钮间距 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义验证码输入框样式 */
|
||||||
|
.custom-code-input {
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
.warn-icon {
|
||||||
|
margin-top: 80px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.warn-title {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #000000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.warn-content {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
/* 穿透修改 Naive UI 输入框样式 */
|
||||||
|
:deep(.custom-code-input .n-input-wrapper) {
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
:deep(.custom-code-input .n-input__input-el) {
|
||||||
|
height: 100%;
|
||||||
|
line-height: 40px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 输入框 hover 状态 */
|
||||||
|
.custom-code-input:hover {
|
||||||
|
border-color: #a3011380; /* 半透明红 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 输入框 聚焦状态 */
|
||||||
|
:deep(.custom-code-input .n-input-wrapper:focus-within) {
|
||||||
|
border-color: #a30113;
|
||||||
|
box-shadow: 0 0 0 2px rgba(163, 1, 19, 0.1);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 输入框 错误状态 */
|
||||||
|
:deep(.n-form-item--error .custom-code-input) {
|
||||||
|
border-color: #d03050;
|
||||||
|
}
|
||||||
|
:deep(.n-form-item--error .custom-code-input .n-input-wrapper:focus-within) {
|
||||||
|
border-color: #d03050;
|
||||||
|
box-shadow: 0 0 0 2px rgba(208, 48, 80, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 验证码按钮样式 */
|
||||||
|
.send-code-btn {
|
||||||
|
height: 100%;
|
||||||
|
min-width: 120px;
|
||||||
|
padding: 0 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #a30113;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
white-space: nowrap;
|
||||||
|
background: #a3011332;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 按钮 hover(非禁用) */
|
||||||
|
.send-code-btn:not(:disabled):hover {
|
||||||
|
background: #a3011332;
|
||||||
|
color: #a30113;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 按钮 点击态 */
|
||||||
|
.send-code-btn:not(:disabled):active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 按钮 禁用态 */
|
||||||
|
.send-code-btn:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 注销按钮样式 */
|
||||||
|
.logout-btn {
|
||||||
|
margin: auto;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 48px;
|
||||||
|
font-size: 16px;
|
||||||
|
width: 180px;
|
||||||
|
height: 40px;
|
||||||
|
background: #a30113;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 注销按钮 hover(非禁用) */
|
||||||
|
.logout-btn:not(:disabled):hover {
|
||||||
|
background: #a30113;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 注销按钮 禁用态 */
|
||||||
|
.logout-btn:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
.title-bar {
|
||||||
|
width: 6px;
|
||||||
|
height: 24px;
|
||||||
|
background: #a30113;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单错误提示位置调整 */
|
||||||
|
:deep(.n-form-item-feedback-wrapper) {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
padding-top: 2px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.custom-code-input) {
|
||||||
|
/* Chrome/Safari/Edge */
|
||||||
|
input::-webkit-outer-spin-button,
|
||||||
|
input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
/* Firefox */
|
||||||
|
input[type='number'] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.n-button__content) {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -6,6 +6,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="user-phone">{{ userPhone || '18988880000' }}</div>
|
<div class="user-phone">{{ userPhone || '18988880000' }}</div>
|
||||||
<div class="valuation-count">剩余评估次数:{{ valuationCount }}</div>
|
<div class="valuation-count">剩余评估次数:{{ valuationCount }}</div>
|
||||||
|
|
||||||
|
<div class="logout-btn" @click="logout">退出登录</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="menu-list">
|
<div class="menu-list">
|
||||||
@ -29,24 +31,48 @@
|
|||||||
import iconHistory from '@/assets/icon/估值记录.png'
|
import iconHistory from '@/assets/icon/估值记录.png'
|
||||||
import iconTransfer from '@/assets/icon/对公转账.png'
|
import iconTransfer from '@/assets/icon/对公转账.png'
|
||||||
import iconInvoice from '@/assets/icon/抬头管理.png'
|
import iconInvoice from '@/assets/icon/抬头管理.png'
|
||||||
|
import iconLogout from '@/assets/icon/iconLogout.png'
|
||||||
|
import { useDialog } from 'naive-ui'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const dialog = useDialog()
|
||||||
defineProps({
|
defineProps({
|
||||||
userPhone: String,
|
userPhone: String,
|
||||||
valuationCount: Number,
|
valuationCount: Number,
|
||||||
currentMenu: String,
|
currentMenu: String,
|
||||||
menuList: Array
|
menuList: Array,
|
||||||
})
|
})
|
||||||
|
|
||||||
defineEmits(['menu-click'])
|
defineEmits(['menu-click'])
|
||||||
|
|
||||||
function getMenuIcon(id) {
|
function getMenuIcon(id) {
|
||||||
const iconMap = {
|
const iconMap = {
|
||||||
'history': iconHistory,
|
history: iconHistory,
|
||||||
'transfer': iconTransfer,
|
transfer: iconTransfer,
|
||||||
'invoice': iconInvoice
|
invoice: iconInvoice,
|
||||||
|
logout: iconLogout,
|
||||||
}
|
}
|
||||||
return iconMap[id]
|
return iconMap[id]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function logout() {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
dialog.warning({
|
||||||
|
title: '提示',
|
||||||
|
content: '确认退出登录',
|
||||||
|
positiveText: '确认',
|
||||||
|
negativeText: '取消',
|
||||||
|
onPositiveClick: () => resolve(),
|
||||||
|
onNegativeClick: () => reject('cancel'),
|
||||||
|
onClose: () => reject('cancel'),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// 清除本地缓存
|
||||||
|
localStorage.removeItem('ACCESS_TOKEN')
|
||||||
|
// 跳转到登录页
|
||||||
|
router.push('/login')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@ -117,12 +143,12 @@ function getMenuIcon(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.menu-item:hover {
|
.menu-item:hover {
|
||||||
background: #F5F7FA;
|
background: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item.active {
|
.menu-item.active {
|
||||||
background: #FFF0F0;
|
background: #fff0f0;
|
||||||
color: #A30113;
|
color: #a30113;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +179,19 @@ function getMenuIcon(id) {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logout-btn {
|
||||||
|
width: 168px;
|
||||||
|
height: 32px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
line-height: 32px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.sidebar-card {
|
.sidebar-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -217,10 +217,10 @@ onMounted(fetchHistory)
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title-bar {
|
.title-bar {
|
||||||
width: 4px;
|
width: 6px;
|
||||||
height: 16px;
|
height: 24px;
|
||||||
background: #a30113;
|
background: #a30113;
|
||||||
border-radius: 2px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-text {
|
.title-text {
|
||||||
|
|||||||
@ -16,23 +16,19 @@
|
|||||||
|
|
||||||
<!-- 右侧内容区 -->
|
<!-- 右侧内容区 -->
|
||||||
<div class="content-area">
|
<div class="content-area">
|
||||||
<!-- 返回按钮 (暂时注释) -->
|
|
||||||
<!-- <div class="back-button" @click="handleBackToHome">
|
|
||||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
<span>返回首页</span>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<!-- 子路由视图 -->
|
<!-- 子路由视图 -->
|
||||||
<router-view
|
<router-view
|
||||||
:asset-list="assetList"
|
:asset-list="assetList"
|
||||||
:invoice-list="invoiceList"
|
:invoice-list="invoiceList"
|
||||||
|
:user-phone="userPhone"
|
||||||
|
:deleteAble="deleteAble"
|
||||||
@return-home="handleBackToHome"
|
@return-home="handleBackToHome"
|
||||||
@add-invoice="addInvoice"
|
@add-invoice="addInvoice"
|
||||||
@update-invoice="updateInvoice"
|
@update-invoice="updateInvoice"
|
||||||
@delete-invoice="deleteInvoice"
|
@delete-invoice="deleteInvoice"
|
||||||
@upload-submit="uploadSubmit"
|
@upload-submit="uploadSubmit"
|
||||||
|
@send-code="sendVerificationCode"
|
||||||
|
@confirm-logout="confirmAccountLogout"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -40,12 +36,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, h, watch, computed } from 'vue'
|
import { ref, onMounted, computed } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
import { useMessage, useDialog } from 'naive-ui' // 引入 Naive UI 消息/弹窗
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import AppHeader from '@/components/AppHeader.vue'
|
import AppHeader from '@/components/AppHeader.vue'
|
||||||
import UserSidebar from './components/UserSidebar.vue'
|
import UserSidebar from './components/UserSidebar.vue'
|
||||||
|
|
||||||
|
// 初始化 Naive UI 消息和弹窗实例
|
||||||
|
const message = useMessage()
|
||||||
|
const dialog = useDialog()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
@ -55,12 +56,14 @@ const currentMenu = computed(() => {
|
|||||||
if (path.includes('/history')) return 'history'
|
if (path.includes('/history')) return 'history'
|
||||||
if (path.includes('/transfer')) return 'transfer'
|
if (path.includes('/transfer')) return 'transfer'
|
||||||
if (path.includes('/invoice')) return 'invoice'
|
if (path.includes('/invoice')) return 'invoice'
|
||||||
|
if (path.includes('/logout')) return 'logout' // 新增:注销菜单匹配
|
||||||
return 'history'
|
return 'history'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 用户信息
|
// 用户信息
|
||||||
const userPhone = ref('')
|
const userPhone = ref('')
|
||||||
const valuationCount = ref(0)
|
const valuationCount = ref(0)
|
||||||
|
const deleteAble = ref(true)
|
||||||
|
|
||||||
// 资产列表
|
// 资产列表
|
||||||
const assetList = ref([])
|
const assetList = ref([])
|
||||||
@ -68,7 +71,7 @@ const assetList = ref([])
|
|||||||
// 开票列表
|
// 开票列表
|
||||||
const invoiceList = ref([])
|
const invoiceList = ref([])
|
||||||
|
|
||||||
// 菜单列表
|
// 菜单列表(新增注销菜单)
|
||||||
const menuList = ref([
|
const menuList = ref([
|
||||||
{
|
{
|
||||||
id: 'history',
|
id: 'history',
|
||||||
@ -82,6 +85,10 @@ const menuList = ref([
|
|||||||
id: 'invoice',
|
id: 'invoice',
|
||||||
label: '抬头管理',
|
label: '抬头管理',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'logout', // 新增:注销账号菜单
|
||||||
|
label: '账号注销',
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
// 返回首页
|
// 返回首页
|
||||||
@ -91,7 +98,6 @@ function handleBackToHome() {
|
|||||||
|
|
||||||
// 菜单点击
|
// 菜单点击
|
||||||
function handleMenuClick(menu) {
|
function handleMenuClick(menu) {
|
||||||
// 使用路由导航
|
|
||||||
router.push(`/user-center/${menu.id}`)
|
router.push(`/user-center/${menu.id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,10 +120,12 @@ async function loadData() {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载估值记录失败:', error)
|
console.error('加载估值记录失败:', error)
|
||||||
$message.error('加载估值记录失败,请稍后重试')
|
// 替换:ElMessage → message
|
||||||
|
message.error('加载估值记录失败,请稍后重试')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//加载发票抬头列表
|
|
||||||
|
// 加载发票抬头列表
|
||||||
async function loadInvoiceList() {
|
async function loadInvoiceList() {
|
||||||
try {
|
try {
|
||||||
const res = await api.getInvoiceHeaders()
|
const res = await api.getInvoiceHeaders()
|
||||||
@ -127,37 +135,43 @@ async function loadInvoiceList() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//添加发票抬头
|
// 添加发票抬头
|
||||||
async function addInvoice(data) {
|
async function addInvoice(data) {
|
||||||
try {
|
try {
|
||||||
await api.addInvoiceHeaders(data)
|
await api.addInvoiceHeaders(data)
|
||||||
$message.success('添加成功')
|
// 替换:ElMessage → message
|
||||||
|
message.success('添加成功')
|
||||||
loadInvoiceList()
|
loadInvoiceList()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('新增发票抬头失败:', error)
|
console.error('新增发票抬头失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//更新发票抬头
|
|
||||||
|
// 更新发票抬头
|
||||||
async function updateInvoice(data) {
|
async function updateInvoice(data) {
|
||||||
try {
|
try {
|
||||||
await api.updateInvoiceHeaders(data)
|
await api.updateInvoiceHeaders(data)
|
||||||
$message.success('编辑成功')
|
// 替换:ElMessage → message
|
||||||
|
message.success('编辑成功')
|
||||||
loadInvoiceList()
|
loadInvoiceList()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新发票抬头失败:', error)
|
console.error('更新发票抬头失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//删除发票抬头
|
|
||||||
|
// 删除发票抬头
|
||||||
async function deleteInvoice(data) {
|
async function deleteInvoice(data) {
|
||||||
try {
|
try {
|
||||||
await api.deleteInvoiceHeaders(data.id)
|
await api.deleteInvoiceHeaders(data.id)
|
||||||
$message.success('删除成功')
|
// 替换:ElMessage → message
|
||||||
|
message.success('删除成功')
|
||||||
loadInvoiceList()
|
loadInvoiceList()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('删除发票抬头失败:', error)
|
console.error('删除发票抬头失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//上传对公转账凭证
|
|
||||||
|
// 上传对公转账凭证
|
||||||
async function uploadSubmit(data) {
|
async function uploadSubmit(data) {
|
||||||
try {
|
try {
|
||||||
console.log('上传对公转账凭证===', data)
|
console.log('上传对公转账凭证===', data)
|
||||||
@ -167,6 +181,53 @@ async function uploadSubmit(data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 新增:发送注销验证码
|
||||||
|
async function sendVerificationCode(phone) {
|
||||||
|
try {
|
||||||
|
await api.sendVerifyCode({ phone })
|
||||||
|
message.success('验证码已发送,请注意查收')
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
console.error('发送验证码失败:', error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增:确认注销账号
|
||||||
|
async function confirmAccountLogout(formData) {
|
||||||
|
// 替换:ElMessageBox.confirm → dialog.warning
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
dialog.warning({
|
||||||
|
title: '提示',
|
||||||
|
content: '提交后账号将注销,不可撤回,确认注销账户?',
|
||||||
|
positiveText: '确认',
|
||||||
|
negativeText: '取消',
|
||||||
|
onPositiveClick: () => resolve(),
|
||||||
|
onNegativeClick: () => reject('cancel'),
|
||||||
|
onClose: () => reject('cancel'),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 调用注销接口(传入手机号和验证码)
|
||||||
|
api
|
||||||
|
.deleteAccount({
|
||||||
|
code: formData.code,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
console.log(res, '111111111111111')
|
||||||
|
// 替换:ElMessage → message
|
||||||
|
message.success('账号注销成功')
|
||||||
|
// 清除本地缓存
|
||||||
|
localStorage.removeItem('phone')
|
||||||
|
// 跳转到登录页
|
||||||
|
router.push('/login')
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err, '111111111111111')
|
||||||
|
deleteAble.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadData()
|
loadData()
|
||||||
loadInvoiceList()
|
loadInvoiceList()
|
||||||
@ -200,26 +261,7 @@ onMounted(() => {
|
|||||||
min-height: calc(100vh - 100px); /* Adjust based on header + margin */
|
min-height: calc(100vh - 100px); /* Adjust based on header + margin */
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden; /* Ensure rounded corners */
|
overflow: hidden; /* Ensure rounded corners */
|
||||||
}
|
padding: 20px; /* 新增:添加内边距 */
|
||||||
|
|
||||||
.back-button {
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
left: 20px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
padding: 0;
|
|
||||||
color: #606266;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
font-size: 14px;
|
|
||||||
background: transparent;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-button:hover {
|
|
||||||
color: #a30113;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
@ -232,9 +274,5 @@ onMounted(() => {
|
|||||||
.main-container {
|
.main-container {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
|
||||||
padding: 10px 20px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user