update
This commit is contained in:
parent
54be0f58f2
commit
cdd46d912e
@ -45,4 +45,22 @@ export function submitUserAuth(data) {
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 发送验证码
|
||||
export function sendCode(data) {
|
||||
return request({
|
||||
url: '/api/user/send-code',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
export function changePassword(data) {
|
||||
return request({
|
||||
url: '/api/user/change-password',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
@ -11,6 +11,9 @@
|
||||
v-model:openKeys="openKeys"
|
||||
theme="dark"
|
||||
mode="inline"
|
||||
:inline-collapsed="collapsed"
|
||||
:defaultOpenKeys="['finance']"
|
||||
:defaultSelectedKeys="['dashboard']"
|
||||
style="background: #1a1a1a;"
|
||||
>
|
||||
<a-menu-item key="dashboard" @click="() => $router.push('/dashboard')">
|
||||
@ -72,6 +75,9 @@
|
||||
</a>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1">
|
||||
<a href="javascript:;" @click="changePasswordVisible = true">修改密码</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="0">
|
||||
<a href="javascript:;" @click="handleLogout">退出登录</a>
|
||||
</a-menu-item>
|
||||
@ -93,6 +99,7 @@
|
||||
蜂快 · 运营商平台 ©2025
|
||||
</a-layout-footer> -->
|
||||
</a-layout>
|
||||
<change-password v-model:visible="changePasswordVisible" />
|
||||
</a-layout>
|
||||
</template>
|
||||
|
||||
@ -109,6 +116,7 @@ import {
|
||||
UserOutlined,
|
||||
ProfileOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import ChangePassword from '../views/ChangePassword.vue';
|
||||
|
||||
export default {
|
||||
name: 'AdminLayout',
|
||||
@ -119,12 +127,14 @@ export default {
|
||||
CreditCardOutlined,
|
||||
WalletOutlined,
|
||||
UserOutlined,
|
||||
ProfileOutlined
|
||||
ProfileOutlined,
|
||||
ChangePassword
|
||||
},
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const changePasswordVisible = ref(false);
|
||||
|
||||
const collapsed = computed({
|
||||
get: () => store.getters.sidebarCollapsed,
|
||||
@ -132,7 +142,7 @@ export default {
|
||||
});
|
||||
|
||||
const userInfo = computed(() => store.getters.userInfo);
|
||||
const selectedKeys = ref([]);
|
||||
const selectedKeys = ref(['dashboard']);
|
||||
const openKeys = ref(['finance']);
|
||||
|
||||
// 获取当前页面标题
|
||||
@ -176,7 +186,8 @@ export default {
|
||||
userInfo,
|
||||
handleLogout,
|
||||
currentPageTitle,
|
||||
route
|
||||
route,
|
||||
changePasswordVisible
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -65,6 +65,12 @@ const routes = [
|
||||
name: 'UserAuth',
|
||||
component: () => import('../views/UserAuth.vue'),
|
||||
meta: { title: '实名认证', icon: 'user' }
|
||||
},
|
||||
{
|
||||
path: 'user/change-password',
|
||||
name: 'ChangePassword',
|
||||
component: () => import('../views/ChangePassword.vue'),
|
||||
meta: { title: '修改密码', icon: 'lock' }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
249
src/views/ChangePassword.vue
Normal file
249
src/views/ChangePassword.vue
Normal file
@ -0,0 +1,249 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:visible="visible"
|
||||
@update:visible="$emit('update:visible', $event)"
|
||||
title="修改密码"
|
||||
:confirm-loading="loading"
|
||||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
:maskClosable="false"
|
||||
:keyboard="false"
|
||||
width="400px"
|
||||
:destroyOnClose="true"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formState"
|
||||
name="changePassword"
|
||||
:rules="rules"
|
||||
class="password-form"
|
||||
>
|
||||
<a-form-item name="phone">
|
||||
<a-input
|
||||
v-model:value="formState.phone"
|
||||
placeholder="请输入手机号"
|
||||
:maxLength="11"
|
||||
class="input-item"
|
||||
disabled
|
||||
>
|
||||
<template #prefix>
|
||||
<mobile-outlined />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="verify_code">
|
||||
<div class="verify-code-input">
|
||||
<a-input
|
||||
v-model:value="formState.verify_code"
|
||||
placeholder="请输入验证码"
|
||||
:maxLength="6"
|
||||
class="input-item"
|
||||
>
|
||||
<template #prefix>
|
||||
<safety-certificate-outlined />
|
||||
</template>
|
||||
</a-input>
|
||||
<a-button
|
||||
type="primary"
|
||||
:disabled="!!countdown"
|
||||
@click="handleSendCode"
|
||||
class="send-code-btn"
|
||||
>
|
||||
{{ countdown ? `${countdown}s后重试` : '获取验证码' }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="new_password">
|
||||
<a-input-password
|
||||
v-model:value="formState.new_password"
|
||||
placeholder="请输入新密码"
|
||||
class="input-item"
|
||||
>
|
||||
<template #prefix>
|
||||
<lock-outlined />
|
||||
</template>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="confirm_password">
|
||||
<a-input-password
|
||||
v-model:value="formState.confirm_password"
|
||||
placeholder="请确认新密码"
|
||||
class="input-item"
|
||||
>
|
||||
<template #prefix>
|
||||
<lock-outlined />
|
||||
</template>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive, watch, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useStore } from 'vuex';
|
||||
import {
|
||||
LockOutlined,
|
||||
MobileOutlined,
|
||||
SafetyCertificateOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { sendCode, changePassword } from '../api/user';
|
||||
|
||||
export default {
|
||||
name: 'ChangePassword',
|
||||
components: {
|
||||
LockOutlined,
|
||||
MobileOutlined,
|
||||
SafetyCertificateOutlined
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
emits: ['update:visible'],
|
||||
setup(props, { emit }) {
|
||||
const store = useStore();
|
||||
const loading = ref(false);
|
||||
const countdown = ref(0);
|
||||
const formRef = ref(null);
|
||||
let countdownTimer = null;
|
||||
|
||||
const formState = reactive({
|
||||
phone: '',
|
||||
verify_code: '',
|
||||
new_password: '',
|
||||
confirm_password: ''
|
||||
});
|
||||
|
||||
const validateConfirmPassword = async (rule, value) => {
|
||||
if (!value) {
|
||||
return Promise.reject('请确认新密码');
|
||||
}
|
||||
if (value !== formState.new_password) {
|
||||
return Promise.reject('两次输入的密码不一致');
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const rules = {
|
||||
verify_code: [{ required: true, message: '请输入验证码' }],
|
||||
new_password: [
|
||||
{ required: true, message: '请输入新密码' },
|
||||
{ min: 6, message: '密码长度不能小于6位' }
|
||||
],
|
||||
confirm_password: [{ required: true, validator: validateConfirmPassword }]
|
||||
};
|
||||
|
||||
const startCountdown = () => {
|
||||
countdown.value = 60;
|
||||
countdownTimer = setInterval(() => {
|
||||
countdown.value--;
|
||||
if (countdown.value <= 0) {
|
||||
clearInterval(countdownTimer);
|
||||
countdownTimer = null;
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const handleSendCode = async () => {
|
||||
try {
|
||||
await sendCode({ phone: formState.phone });
|
||||
message.success('验证码已发送');
|
||||
startCountdown();
|
||||
} catch (error) {
|
||||
message.error(error.message || '发送验证码失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
loading.value = true;
|
||||
await changePassword({
|
||||
phone: formState.phone,
|
||||
verify_code: formState.verify_code,
|
||||
new_password: formState.new_password
|
||||
});
|
||||
message.success('密码修改成功');
|
||||
handleCancel();
|
||||
} catch (error) {
|
||||
if (error.message) {
|
||||
message.error(error.message);
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
// 清空表单
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
// 重置倒计时
|
||||
countdown.value = 0;
|
||||
if (countdownTimer) {
|
||||
clearInterval(countdownTimer);
|
||||
countdownTimer = null;
|
||||
}
|
||||
// 关闭模态框
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
// 监听visible变化,当显示时设置手机号
|
||||
watch(() => props.visible, (val) => {
|
||||
if (val) {
|
||||
const userInfo = store.getters.userInfo;
|
||||
if (userInfo && userInfo.phone) {
|
||||
formState.phone = userInfo.phone;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 组件卸载前清理
|
||||
onBeforeUnmount(() => {
|
||||
if (countdownTimer) {
|
||||
clearInterval(countdownTimer);
|
||||
countdownTimer = null;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
formRef,
|
||||
formState,
|
||||
rules,
|
||||
loading,
|
||||
countdown,
|
||||
handleSubmit,
|
||||
handleSendCode,
|
||||
handleCancel
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.password-form {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.input-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.verify-code-input {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.send-code-btn {
|
||||
white-space: nowrap;
|
||||
min-width: 120px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user