11
This commit is contained in:
parent
f175e5159a
commit
45f557c9cb
@ -10,3 +10,9 @@ export const login = (params:any) => request.post('/v1/auth/login', params)
|
|||||||
// export const updateRole = (id, params) => request.basic.put(`/api/v1/roles/${id}`, params)
|
// export const updateRole = (id, params) => request.basic.put(`/api/v1/roles/${id}`, params)
|
||||||
// // 删除role
|
// // 删除role
|
||||||
// export const delRole = (id) => request.basic.delete(`/api/v1/roles/${id}`)
|
// export const delRole = (id) => request.basic.delete(`/api/v1/roles/${id}`)
|
||||||
|
// 修改密码
|
||||||
|
export const updatePassword = (newPassword:any) => request.put('/v1/auth/update_password',newPassword)
|
||||||
|
// 获取用户信息
|
||||||
|
export const fetchUserInfo = () => request.get('/v1/auth/info')
|
||||||
|
// 修改手机号
|
||||||
|
export const updatePhoneNumber = (params:any) => request.put('/v1/auth/update_phone', params)
|
||||||
@ -1,6 +1,109 @@
|
|||||||
<!-- src/components/AccountSecurity.vue -->
|
<!-- src/components/AccountSecurity.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="account-security">
|
||||||
|
<h2>账号安全</h2>
|
||||||
|
<div v-for="(item, index) in securityItems" :key="index" class="security-item">
|
||||||
|
<div class="item-header">
|
||||||
|
<span class="title">{{ item.title }}</span>
|
||||||
|
<div v-if="item.title == '登录密码'">
|
||||||
|
<button class="action-btn" :class="`color-${getActionColor(item.status)}`" @click="item.actionHandler">
|
||||||
|
{{ item.actionText }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="status" v-if="item.title !== '登录密码'">
|
||||||
|
<component :is="getStatusIcon(item.status)" v-if="getStatusIcon(item.status)"
|
||||||
|
:class="['icon', `color-${getStatusColor(item.status)}`]" />
|
||||||
|
<span :class="['text', `color-${getStatusColor(item.status)}`]">
|
||||||
|
{{ item.status === 'bound' ? '已绑定' : item.status === 'unverified' ? '未认证' : '未设置' }}
|
||||||
|
</span>
|
||||||
|
<span class="divider">|</span>
|
||||||
|
<button class="action-btn" :class="`color-${getActionColor(item.status)}`" @click="item.actionHandler">
|
||||||
|
{{ item.actionText }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="description">{{ item.description }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 设置密码弹窗 -->
|
||||||
|
<a-modal v-model:visible="setPasswordModalVisible" title="设置密码" width="500px" :footer="null"
|
||||||
|
@cancel="closeSetPasswordModal">
|
||||||
|
<div style="padding: 24px 0;">
|
||||||
|
<div style="margin-bottom: 24px; font-size: 16px; color: #333;">
|
||||||
|
手机号:<span>{{ userPhone }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="color: red;">*</span>
|
||||||
|
<label style="font-size: 14px; color: #333;">手机验证码:</label>
|
||||||
|
<a-input v-model:value="passwordForm.smsCode" placeholder="请输入验证码" style="flex: 1;" />
|
||||||
|
<a-button type="primary" :disabled="isSending || countdown > 0" @click="sendSmsCode('password')"
|
||||||
|
style="width: 120px;">
|
||||||
|
{{ isSending || countdown > 0 ? `${countdown}s后重发` : '发送验证码' }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="color: red;">*</span>
|
||||||
|
<label style="font-size: 14px; color: #333;">设置新密码:</label>
|
||||||
|
<a-input v-model:value="passwordForm.newPassword" placeholder="请输入8~16位包含数字和字母的密码" type="password"
|
||||||
|
style="flex: 1;" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="color: red;">*</span>
|
||||||
|
<label style="font-size: 14px; color: #333;">确认新密码:</label>
|
||||||
|
<a-input v-model:value="passwordForm.confirmPassword" placeholder="请确认密码" type="password" style="flex: 1;" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: right; padding: 16px 24px;">
|
||||||
|
<a-button @click="closeSetPasswordModal" style="margin-right: 8px;">取消</a-button>
|
||||||
|
<a-button type="primary" @click="savePassword">保存</a-button>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<!-- 修改手机号弹窗 -->
|
||||||
|
<a-modal v-model:visible="editPhoneModalVisible" title="修改手机号" width="500px" :footer="null"
|
||||||
|
@cancel="closeEditPhoneModal">
|
||||||
|
<div style="padding: 24px 0;">
|
||||||
|
<div style="margin-bottom: 24px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="color: red;">*</span>
|
||||||
|
<label style="font-size: 14px; color: #333;">输入新手机号:</label>
|
||||||
|
<a-select v-model:value="phoneForm.countryCode" style="width: 80px;" placeholder="+86">
|
||||||
|
<a-select-option value="+86">+86</a-select-option>
|
||||||
|
<a-select-option value="+852">+852</a-select-option>
|
||||||
|
<a-select-option value="+853">+853</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-input v-model:value="phoneForm.newPhoneNumber" placeholder="请输入新手机号" style="flex: 1;" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="color: red;">*</span>
|
||||||
|
<label style="font-size: 14px; color: #333;">手机验证码:</label>
|
||||||
|
<a-input v-model:value="phoneForm.smsCode" placeholder="请输入验证码" style="flex: 1;" />
|
||||||
|
<a-button type="primary" :disabled="isSending || countdown > 0" @click="sendSmsCode('phone')"
|
||||||
|
style="width: 120px;">
|
||||||
|
{{ isSending || countdown > 0 ? `${countdown}s后重发` : '发送验证码' }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="color: red;">*</span>
|
||||||
|
<label style="font-size: 14px; color: #333;">输入账号密码:</label>
|
||||||
|
<a-input v-model:value="phoneForm.password" placeholder="请输入账号登录密码" type="password" style="flex: 1;" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: right; padding: 16px 24px;">
|
||||||
|
<a-button @click="closeEditPhoneModal" style="margin-right: 8px;">取消</a-button>
|
||||||
|
<a-button type="primary" @click="savePhone">确定</a-button>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive } from 'vue';
|
import { ref, reactive, onBeforeMount, computed } from 'vue';
|
||||||
import {
|
import {
|
||||||
CheckCircleOutlined,
|
CheckCircleOutlined,
|
||||||
ExclamationCircleOutlined,
|
ExclamationCircleOutlined,
|
||||||
@ -10,9 +113,15 @@ import {
|
|||||||
import { Modal, message } from 'ant-design-vue';
|
import { Modal, message } from 'ant-design-vue';
|
||||||
// 在 <script setup> 中引入 router
|
// 在 <script setup> 中引入 router
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
import { updatePassword, updatePhoneNumber } from '@/apis/login';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const userPhone = ref('')
|
||||||
|
onBeforeMount(() => {
|
||||||
|
// 模拟获取用户手机号
|
||||||
|
console.log(1111)
|
||||||
|
userPhone.value = JSON.parse(localStorage.getItem('userInfo') || '{}').phone
|
||||||
|
})
|
||||||
const getStatusIcon = (status: SecurityItem['status']) => {
|
const getStatusIcon = (status: SecurityItem['status']) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'bound':
|
case 'bound':
|
||||||
@ -46,24 +155,23 @@ const getActionColor = (status: SecurityItem['status']) => {
|
|||||||
interface SecurityItem {
|
interface SecurityItem {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
status: 'unset' | 'bound' | 'unverified' | 'verified';
|
status?: 'unset' | 'bound' | 'unverified' | 'verified';
|
||||||
actionText: string;
|
actionText?: string;
|
||||||
actionHandler: () => void;
|
actionHandler: () => void;
|
||||||
}
|
}
|
||||||
|
const securityItems = computed<SecurityItem[]>(() => [
|
||||||
const securityItems = ref<SecurityItem[]>([
|
|
||||||
{
|
{
|
||||||
title: '登录密码',
|
title: '登录密码',
|
||||||
description: '安全性高的密码可以使账号更安全。建议您定期更换密码,设置一个包含字母和数字且长度超过8位的密码',
|
description: '安全性高的密码可以使账号更安全。建议您定期更换密码,设置一个包含字母和数字且长度超过8位的密码',
|
||||||
status: 'unset',
|
status: 'bound',
|
||||||
actionText: '设置',
|
actionText: '修改密码',
|
||||||
actionHandler: () => openSetPasswordModal(),
|
actionHandler: () => openSetPasswordModal(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '手机绑定',
|
title: '手机号',
|
||||||
description: '您已绑定了手机178****5075您的手机号可以直接用于登录、找回密码等',
|
description: userPhone.value ? '您已绑定了手机178****5075您的手机号可以直接用于登录、找回密码等' : '未绑定手机',
|
||||||
status: 'bound',
|
status: userPhone.value ? 'bound' : 'unset',
|
||||||
actionText: '修改',
|
actionText: userPhone.value ? '修改手机号' : '绑定手机号',
|
||||||
actionHandler: () => openEditPhoneModal(),
|
actionHandler: () => openEditPhoneModal(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -75,21 +183,33 @@ const securityItems = ref<SecurityItem[]>([
|
|||||||
router.push('/layout/admin/realnameAuth');
|
router.push('/layout/admin/realnameAuth');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// title: '微信绑定',
|
|
||||||
// description: '您已绑定微信,可快速扫码登录',
|
|
||||||
// status: 'bound',
|
|
||||||
// actionText: '解绑',
|
|
||||||
// actionHandler: () => alert('确认解绑微信?'),
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
title: '邮箱绑定(即将上线)',
|
|
||||||
description: '绑定邮箱后可接收系统消息,如余额不足、实例即将到期、实例即将释放等消息',
|
|
||||||
status: 'unset',
|
|
||||||
actionText: '绑定',
|
|
||||||
actionHandler: () => alert('跳转到绑定邮箱页面'),
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
// const securityItems = ref<SecurityItem[]>([
|
||||||
|
// {
|
||||||
|
// title: '登录密码',
|
||||||
|
// description: '安全性高的密码可以使账号更安全。建议您定期更换密码,设置一个包含字母和数字且长度超过8位的密码',
|
||||||
|
// status: 'bound',
|
||||||
|
// actionText: '修改密码',
|
||||||
|
// actionHandler: () => openSetPasswordModal(),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '手机号',
|
||||||
|
// description: userPhone.value?'您已绑定了手机178****5075您的手机号可以直接用于登录、找回密码等':'未绑定手机',
|
||||||
|
// status: userPhone.value?'bound':'unset',
|
||||||
|
// actionText: userPhone.value?'修改手机号':'绑定手机号',
|
||||||
|
// actionHandler: () => openEditPhoneModal(),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '实名认证',
|
||||||
|
// description: '实名认证后可以使用AutoDL更完整的功能,如打开实例的自定义服务等',
|
||||||
|
// status: 'unverified',
|
||||||
|
// actionText: '立即认证',
|
||||||
|
// actionHandler: () => {
|
||||||
|
// router.push('/layout/admin/realnameAuth');
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
|
||||||
|
// ]);
|
||||||
|
|
||||||
// 设置密码弹窗
|
// 设置密码弹窗
|
||||||
const setPasswordModalVisible = ref(false);
|
const setPasswordModalVisible = ref(false);
|
||||||
@ -109,6 +229,7 @@ const closeRealNameAuthModal = () => {
|
|||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const passwordForm = reactive({
|
const passwordForm = reactive({
|
||||||
|
phone: userPhone.value,
|
||||||
smsCode: '',
|
smsCode: '',
|
||||||
newPassword: '',
|
newPassword: '',
|
||||||
confirmPassword: '',
|
confirmPassword: '',
|
||||||
@ -185,7 +306,7 @@ const resetPhoneForm = () => {
|
|||||||
|
|
||||||
|
|
||||||
// 保存密码
|
// 保存密码
|
||||||
const savePassword = () => {
|
const savePassword = async () => {
|
||||||
if (!passwordForm.smsCode) {
|
if (!passwordForm.smsCode) {
|
||||||
message.error('请输入验证码');
|
message.error('请输入验证码');
|
||||||
return;
|
return;
|
||||||
@ -206,13 +327,28 @@ const savePassword = () => {
|
|||||||
message.error('密码必须为8~16位,且包含字母和数字');
|
message.error('密码必须为8~16位,且包含字母和数字');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
const passwordData = {
|
||||||
|
phone: userPhone.value,
|
||||||
|
code: passwordForm.smsCode,
|
||||||
|
confirmPassword: passwordForm.confirmPassword,
|
||||||
|
newPassword: passwordForm.newPassword
|
||||||
|
};
|
||||||
|
const res = await updatePassword(passwordData);
|
||||||
|
message.success('密码设置成功!');
|
||||||
|
setTimeout(() => {
|
||||||
|
localStorage.clear();
|
||||||
|
router.replace('/login');
|
||||||
|
}, 1500);
|
||||||
|
closeSetPasswordModal();
|
||||||
|
} catch (error: any) {
|
||||||
|
message.error(error);
|
||||||
|
}
|
||||||
|
|
||||||
message.success('密码设置成功!');
|
|
||||||
closeSetPasswordModal();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 保存手机号
|
// 保存手机号
|
||||||
const savePhone = () => {
|
const savePhone = async () => {
|
||||||
if (!phoneForm.newPhoneNumber) {
|
if (!phoneForm.newPhoneNumber) {
|
||||||
message.error('请输入新手机号');
|
message.error('请输入新手机号');
|
||||||
return;
|
return;
|
||||||
@ -229,166 +365,24 @@ const savePhone = () => {
|
|||||||
message.error('请输入账号登录密码');
|
message.error('请输入账号登录密码');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
message.success('手机号修改成功!');
|
const phoneData = {
|
||||||
closeEditPhoneModal();
|
newPhone: phoneForm.newPhoneNumber,
|
||||||
|
code: phoneForm.smsCode,
|
||||||
|
Password: phoneForm.password
|
||||||
|
};
|
||||||
|
await updatePhoneNumber(phoneData);
|
||||||
|
message.success('手机号修改成功!');
|
||||||
|
closeEditPhoneModal();
|
||||||
|
setTimeout(() => {
|
||||||
|
localStorage.clear();
|
||||||
|
router.replace('/login');
|
||||||
|
}, 1500);
|
||||||
|
} catch (error: any) {
|
||||||
|
message.error(error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="account-security">
|
|
||||||
<h2>账号安全</h2>
|
|
||||||
<div v-for="(item, index) in securityItems" :key="index" class="security-item">
|
|
||||||
<div class="item-header">
|
|
||||||
<span class="title">{{ item.title }}</span>
|
|
||||||
<div class="status">
|
|
||||||
<component
|
|
||||||
:is="getStatusIcon(item.status)"
|
|
||||||
v-if="getStatusIcon(item.status)"
|
|
||||||
:class="['icon', `color-${getStatusColor(item.status)}`]"
|
|
||||||
/>
|
|
||||||
<span :class="['text', `color-${getStatusColor(item.status)}`]">
|
|
||||||
{{ item.status === 'bound' ? '已绑定' : item.status === 'unverified' ? '未认证' : '未设置' }}
|
|
||||||
</span>
|
|
||||||
<span class="divider">|</span>
|
|
||||||
<button
|
|
||||||
class="action-btn"
|
|
||||||
:class="`color-${getActionColor(item.status)}`"
|
|
||||||
@click="item.actionHandler"
|
|
||||||
>
|
|
||||||
{{ item.actionText }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="description">{{ item.description }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 设置密码弹窗 -->
|
|
||||||
<a-modal
|
|
||||||
v-model:visible="setPasswordModalVisible"
|
|
||||||
title="设置密码"
|
|
||||||
width="500px"
|
|
||||||
:footer="null"
|
|
||||||
@cancel="closeSetPasswordModal"
|
|
||||||
>
|
|
||||||
<div style="padding: 24px 0;">
|
|
||||||
<div style="margin-bottom: 24px; font-size: 16px; color: #333;">
|
|
||||||
手机号:+86 178****5075
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
|
||||||
<span style="color: red;">*</span>
|
|
||||||
<label style="font-size: 14px; color: #333;">手机验证码:</label>
|
|
||||||
<a-input
|
|
||||||
v-model:value="passwordForm.smsCode"
|
|
||||||
placeholder="请输入验证码"
|
|
||||||
style="flex: 1;"
|
|
||||||
/>
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
:disabled="isSending || countdown > 0"
|
|
||||||
@click="sendSmsCode('password')"
|
|
||||||
style="width: 120px;"
|
|
||||||
>
|
|
||||||
{{ isSending || countdown > 0 ? `${countdown}s后重发` : '发送验证码' }}
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
|
||||||
<span style="color: red;">*</span>
|
|
||||||
<label style="font-size: 14px; color: #333;">设置新密码:</label>
|
|
||||||
<a-input
|
|
||||||
v-model:value="passwordForm.newPassword"
|
|
||||||
placeholder="请输入8~16位包含数字和字母的密码"
|
|
||||||
type="password"
|
|
||||||
style="flex: 1;"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
|
||||||
<span style="color: red;">*</span>
|
|
||||||
<label style="font-size: 14px; color: #333;">确认新密码:</label>
|
|
||||||
<a-input
|
|
||||||
v-model:value="passwordForm.confirmPassword"
|
|
||||||
placeholder="请确认密码"
|
|
||||||
type="password"
|
|
||||||
style="flex: 1;"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="text-align: right; padding: 16px 24px;">
|
|
||||||
<a-button @click="closeSetPasswordModal" style="margin-right: 8px;">取消</a-button>
|
|
||||||
<a-button type="primary" @click="savePassword">保存</a-button>
|
|
||||||
</div>
|
|
||||||
</a-modal>
|
|
||||||
|
|
||||||
<!-- 修改手机号弹窗 -->
|
|
||||||
<a-modal
|
|
||||||
v-model:visible="editPhoneModalVisible"
|
|
||||||
title="修改手机号"
|
|
||||||
width="500px"
|
|
||||||
:footer="null"
|
|
||||||
@cancel="closeEditPhoneModal"
|
|
||||||
>
|
|
||||||
<div style="padding: 24px 0;">
|
|
||||||
<div style="margin-bottom: 24px; display: flex; align-items: center; gap: 8px;">
|
|
||||||
<span style="color: red;">*</span>
|
|
||||||
<label style="font-size: 14px; color: #333;">输入新手机号:</label>
|
|
||||||
<a-select
|
|
||||||
v-model:value="phoneForm.countryCode"
|
|
||||||
style="width: 80px;"
|
|
||||||
placeholder="+86"
|
|
||||||
>
|
|
||||||
<a-select-option value="+86">+86</a-select-option>
|
|
||||||
<a-select-option value="+852">+852</a-select-option>
|
|
||||||
<a-select-option value="+853">+853</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
<a-input
|
|
||||||
v-model:value="phoneForm.newPhoneNumber"
|
|
||||||
placeholder="请输入新手机号"
|
|
||||||
style="flex: 1;"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
|
||||||
<span style="color: red;">*</span>
|
|
||||||
<label style="font-size: 14px; color: #333;">手机验证码:</label>
|
|
||||||
<a-input
|
|
||||||
v-model:value="phoneForm.smsCode"
|
|
||||||
placeholder="请输入验证码"
|
|
||||||
style="flex: 1;"
|
|
||||||
/>
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
:disabled="isSending || countdown > 0"
|
|
||||||
@click="sendSmsCode('phone')"
|
|
||||||
style="width: 120px;"
|
|
||||||
>
|
|
||||||
{{ isSending || countdown > 0 ? `${countdown}s后重发` : '发送验证码' }}
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 8px;">
|
|
||||||
<span style="color: red;">*</span>
|
|
||||||
<label style="font-size: 14px; color: #333;">输入账号密码:</label>
|
|
||||||
<a-input
|
|
||||||
v-model:value="phoneForm.password"
|
|
||||||
placeholder="请输入账号登录密码"
|
|
||||||
type="password"
|
|
||||||
style="flex: 1;"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="text-align: right; padding: 16px 24px;">
|
|
||||||
<a-button @click="closeEditPhoneModal" style="margin-right: 8px;">取消</a-button>
|
|
||||||
<a-button type="primary" @click="savePhone">确定</a-button>
|
|
||||||
</div>
|
|
||||||
</a-modal>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.account-security {
|
.account-security {
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
|||||||
@ -11,25 +11,26 @@
|
|||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<a-dropdown>
|
<a-dropdown>
|
||||||
<div style="display: flex;align-items: center;justify-content: flex-end;">
|
<div style="display: flex;align-items: center;justify-content: flex-end;">
|
||||||
<a-avatar :size="24" :src="avatar">
|
<a-avatar :size="24" :src="userInfo.avatar">
|
||||||
<!-- <template #icon>
|
<!-- <template #icon>
|
||||||
<UserOutlined />
|
<UserOutlined />
|
||||||
</template> -->
|
</template> -->
|
||||||
</a-avatar>
|
</a-avatar>
|
||||||
<span style="font-size: 14px;padding-left:5px;">管理员</span>
|
<span style="font-size: 14px;padding-left:5px;">{{ userInfo.userName }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<a-card hoverable style="width: 300px">
|
<a-card hoverable style="width: 300px">
|
||||||
<template #cover>
|
<template #cover>
|
||||||
<div style="background:#f5f7fa;padding:10px;line-height: 30px">
|
<div style="background:#f5f7fa;padding:10px;line-height: 30px">
|
||||||
<div>管理员<a-tag style="margin-left: 10px;" color="red">未实名</a-tag></div>
|
<div>{{ userInfo.userName }} <a-tag color="blue" style="margin-left: 10px;">{{ userInfo.accountType==='USER'?'个人认证':'企业认证' }}</a-tag></div>
|
||||||
<div>ID:23455522</div>
|
<div>ID:{{ userInfo.id }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding: 10px;line-height: 45px;">
|
<div style="padding: 10px;line-height: 45px;">
|
||||||
<div style="display: flex;justify-content: space-between;align-items: center;"><div>可用余额:¥200.00</div> <a-button type="primary" danger ghost size="small">去充值</a-button></div>
|
<div style="display: flex;justify-content: space-between;align-items: center;"><div>可用余额:¥200.00</div> <a-button type="primary" danger ghost size="small">去充值</a-button></div>
|
||||||
<div>冻结余额:¥100.00</div>
|
<div>实例数量:¥{{ userInfo.caseNum }}</div>
|
||||||
<div>代金劵:¥100.00</div>
|
<div>冻结余额:¥{{ userInfo.freezeBalace }}</div>
|
||||||
|
<div>未冻结余额:¥{{ userInfo.noFreezeBalace }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
@ -56,6 +57,7 @@ import avatar from '@/assets/avator.png'
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const isHome = ref(true)
|
const isHome = ref(true)
|
||||||
|
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}');
|
||||||
// 根据当前路由初始化菜单选中项(去掉 /layout 前缀)
|
// 根据当前路由初始化菜单选中项(去掉 /layout 前缀)
|
||||||
const getActiveKeyFromRoute = () => {
|
const getActiveKeyFromRoute = () => {
|
||||||
const path = route.path
|
const path = route.path
|
||||||
@ -100,6 +102,7 @@ const handleMenuClick = (key) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
|
localStorage.clear()
|
||||||
router.replace('/login')
|
router.replace('/login')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref, shallowRef } from 'vue';
|
import { reactive, ref, shallowRef } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { login } from '@/apis/login';
|
import { login, fetchUserInfo } from '@/apis/login';
|
||||||
import { message, type FormInstance } from 'ant-design-vue';
|
import { message, type FormInstance } from 'ant-design-vue';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -55,7 +55,7 @@ const onFinish = async (values: FormState) => {
|
|||||||
|
|
||||||
const loginData = {
|
const loginData = {
|
||||||
...values,
|
...values,
|
||||||
login_method: 'SMS'
|
login_method: 'PWD'//PWD表示密码登录,SMS表示短信验证码登录
|
||||||
};
|
};
|
||||||
formRef.value?.validateFields().then(async () => {
|
formRef.value?.validateFields().then(async () => {
|
||||||
try {
|
try {
|
||||||
@ -67,6 +67,8 @@ const onFinish = async (values: FormState) => {
|
|||||||
throw new Error('登录失败:未返回有效凭证');
|
throw new Error('登录失败:未返回有效凭证');
|
||||||
}
|
}
|
||||||
localStorage.setItem('token', token);
|
localStorage.setItem('token', token);
|
||||||
|
const userRes=await fetchUserInfo();
|
||||||
|
localStorage.setItem('userInfo', JSON.stringify(userRes));
|
||||||
router.push('/layout/home');
|
router.push('/layout/home');
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('登录请求失败:', error);
|
console.error('登录请求失败:', error);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user