feat: 增加忘记密码
parent
ce41faacc5
commit
edfe5a56e2
|
|
@ -26,6 +26,9 @@ declare module 'vue' {
|
||||||
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
||||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
||||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||||
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||||
Empty: typeof import('./src/components/empty/Empty.vue')['default']
|
Empty: typeof import('./src/components/empty/Empty.vue')['default']
|
||||||
ImageCropper: typeof import('./src/components/image-cropper/index.vue')['default']
|
ImageCropper: typeof import('./src/components/image-cropper/index.vue')['default']
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,12 @@ export function logout() {
|
||||||
}
|
}
|
||||||
export function getConfig(params) {
|
export function getConfig(params) {
|
||||||
return request.get('/sms/v1/logo', {
|
return request.get('/sms/v1/logo', {
|
||||||
params: wrapperParams(params),
|
params: wrapperParams(params)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function getDict(data) {
|
export function getDict(data) {
|
||||||
return request.get('/dict/children', {
|
return request.get('/dict/children', {
|
||||||
params: wrapperParams(data),
|
params: wrapperParams(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function getSysconf() {
|
export function getSysconf() {
|
||||||
|
|
@ -48,7 +48,7 @@ export function getPortal(params) {
|
||||||
}
|
}
|
||||||
export function getServiceQuota(tenantId, data) {
|
export function getServiceQuota(tenantId, data) {
|
||||||
return request.get(`/cos/v1/tenants/${tenantId}/quotas`, {
|
return request.get(`/cos/v1/tenants/${tenantId}/quotas`, {
|
||||||
params: wrapperParams(data),
|
params: wrapperParams(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function replaceToken(params) {
|
export function replaceToken(params) {
|
||||||
|
|
@ -69,7 +69,7 @@ export function getSystemTreeConfigs(params) {
|
||||||
// 更新系统配置信息
|
// 更新系统配置信息
|
||||||
export function updateSystemConfigs(params) {
|
export function updateSystemConfigs(params) {
|
||||||
return request.put('/sms/v1/system-configs', params, {
|
return request.put('/sms/v1/system-configs', params, {
|
||||||
headers: { 'Content-Type': 'multipart/form-data', BsmAjaxHeader: true, options: { noSeri: true } },
|
headers: { 'Content-Type': 'multipart/form-data', BsmAjaxHeader: true, options: { noSeri: true } }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 测试连接
|
// 测试连接
|
||||||
|
|
@ -79,3 +79,8 @@ export function testLinkApi(category) {
|
||||||
export function getVertifyCode(params) {
|
export function getVertifyCode(params) {
|
||||||
return request.post('/sms/v1/users/code', wrapperParams(params))
|
return request.post('/sms/v1/users/code', wrapperParams(params))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 忘记密码
|
||||||
|
export function forgetPassword(params) {
|
||||||
|
return request.post('/sms/v1/users/forget', params)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,42 @@
|
||||||
<a-switch v-model:checked="remember"></a-switch>
|
<a-switch v-model:checked="remember"></a-switch>
|
||||||
<span class="m-l-xs">记住密码</span>
|
<span class="m-l-xs">记住密码</span>
|
||||||
</span>
|
</span>
|
||||||
<a :href="`mailto:${configs.helpInformationLink}`" type="text" class="text-info pull-right help-info" :title="configs.helpInformationContent">{{ configs.helpInformationContent }}</a>
|
<a :href="`mailto:${configs.helpInformationLink}`" type="text" class="text-info help-info" :title="configs.helpInformationContent">{{ configs.helpInformationContent }}</a>
|
||||||
|
<a type="text" class="m-l text-info forgot-password" @click="openForgotPasswordDialog">忘记密码</a>
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-button class="login-btn" type="primary" size="medium" :loading="loading" @click="handleLogin">登录</a-button>
|
<a-button class="login-btn" type="primary" size="medium" :loading="loading" @click="handleLogin">登录</a-button>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
<div class="copyright-info">{{ configs.copyrightInformation }}</div>
|
<div class="copyright-info">{{ configs.copyrightInformation }}</div>
|
||||||
|
<!-- 忘记密码弹窗 -->
|
||||||
|
<a-modal title="忘记密码" v-model:visible="showForgotPasswordDialog" width="600px" :confirm-loading="forgotPasswordLoading" @ok="handleForgotPassword" :close-on-click-modal="false">
|
||||||
|
<a-form :model="forgotPasswordForm" ref="forgotPasswordFormRef" label-position="left" :labelCol="{ style: { width: '80px' } }">
|
||||||
|
<a-form-item label="用户名" name="account" :rules="[{ ...required, message: '请输入用户名' }]">
|
||||||
|
<a-input class="w-lg" v-model:value="forgotPasswordForm.account" placeholder="请输入用户名"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="新密码" name="password" :rules="[{ ...required, message: '请输入密码' }]">
|
||||||
|
<a-input class="w-lg" v-model:value="forgotPasswordForm.password" type="password" placeholder="请输入新密码" show-password></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="确认密码" name="confirmPassword" :rules="[{ ...required, message: '请输入密码' }]">
|
||||||
|
<a-input class="w-lg" v-model:value="forgotPasswordForm.confirmPassword" type="password" placeholder="请再次输入新密码" show-password></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="验证码" name="verificationCode" :rules="[{ ...required, message: '请输入验证码' }]">
|
||||||
|
<div class="verification-code-input">
|
||||||
|
<a-input class="w-lg m-r" v-model:value="forgotPasswordForm.verificationCode" placeholder="请输入验证码"></a-input>
|
||||||
|
<a-button type="primary" :disabled="codeCountdown > 0" @click="getVerificationCode" :loading="codeLoading">
|
||||||
|
{{ codeCountdown > 0 ? `${codeCountdown}s后重新获取` : '获取验证码' }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<a-button @click="showForgotPasswordDialog = false">取消</a-button>
|
||||||
|
<a-button type="primary" :loading="forgotPasswordLoading" @click="handleForgotPassword">确定</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -61,8 +90,8 @@ import { useStore } from 'vuex'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import setLoginData from './tools'
|
import setLoginData from './tools'
|
||||||
import { required } from '@/validate'
|
import { required } from '@/validate'
|
||||||
import { getVertifyCode } from '@/services'
|
import { getVertifyCode, forgetPassword } from '@/services'
|
||||||
import { message } from 'ant-design-vue'
|
import { message, Modal } from 'ant-design-vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { UserOutlined, LockOutlined },
|
components: { UserOutlined, LockOutlined },
|
||||||
|
|
@ -78,11 +107,23 @@ export default {
|
||||||
verifyLoading: false,
|
verifyLoading: false,
|
||||||
countdown: 0,
|
countdown: 0,
|
||||||
isCountingDown: false,
|
isCountingDown: false,
|
||||||
needSmsVerify: true
|
needSmsVerify: true,
|
||||||
|
showForgotPasswordDialog: false,
|
||||||
|
forgotPasswordForm: {
|
||||||
|
account: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
verificationCode: ''
|
||||||
|
},
|
||||||
|
forgotPasswordLoading: false,
|
||||||
|
codeCountdown: 0,
|
||||||
|
codeLoading: false
|
||||||
})
|
})
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
const pwdRule = computed(() => store.state.app.systemConfig.pwdStrength + ',pswNoSpace' + ',required')
|
||||||
const configs = computed(() => store.getters.pageConfig)
|
const configs = computed(() => store.getters.pageConfig)
|
||||||
const loginFormRef = ref(null)
|
const loginFormRef = ref(null)
|
||||||
|
const forgotPasswordFormRef = ref(null)
|
||||||
let countdownTimer = null
|
let countdownTimer = null
|
||||||
|
|
||||||
// 开始倒计时
|
// 开始倒计时
|
||||||
|
|
@ -122,12 +163,15 @@ export default {
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
// 监听account变化,如果清空则重置needSmsVerify
|
// 监听account变化,如果清空则重置needSmsVerify
|
||||||
watch(() => state.loginForm.account, (newAccount) => {
|
watch(
|
||||||
if (!newAccount.trim()) {
|
() => state.loginForm.account,
|
||||||
state.needSmsVerify = true
|
(newAccount) => {
|
||||||
resetCountdown() // 同时重置倒计时
|
if (!newAccount.trim()) {
|
||||||
|
state.needSmsVerify = true
|
||||||
|
resetCountdown() // 同时重置倒计时
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
|
||||||
const getVertify = () => {
|
const getVertify = () => {
|
||||||
if (state.isCountingDown) return // 如果正在倒计时,不允许重复点击
|
if (state.isCountingDown) return // 如果正在倒计时,不允许重复点击
|
||||||
|
|
@ -209,6 +253,58 @@ export default {
|
||||||
state.capsTooltip = false
|
state.capsTooltip = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getVerificationCode() {
|
||||||
|
if (!state.forgotPasswordForm.account) {
|
||||||
|
message.error('请先输入用户名')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.codeLoading = true
|
||||||
|
getVertifyCode({ account: state.forgotPasswordForm.account })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
message.success('验证码已发送')
|
||||||
|
state.codeCountdown = 60
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
state.codeCountdown--
|
||||||
|
if (state.codeCountdown <= 0) {
|
||||||
|
clearInterval(timer)
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
state.codeLoading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function openForgotPasswordDialog() {
|
||||||
|
// 将当前登录表单的用户名带入忘记密码表单
|
||||||
|
state.forgotPasswordForm.account = state.loginForm.account
|
||||||
|
state.showForgotPasswordDialog = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleForgotPassword() {
|
||||||
|
forgotPasswordFormRef.value.validate().then(() => {
|
||||||
|
const { account, password, confirmPassword, verificationCode } = state.forgotPasswordForm
|
||||||
|
if (confirmPassword !== password) return message.error('两次输入的密码不相同')
|
||||||
|
state.forgotPasswordLoading = true
|
||||||
|
forgetPassword({
|
||||||
|
account,
|
||||||
|
password: encrypt(password),
|
||||||
|
code: verificationCode
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
message.success(res.message)
|
||||||
|
state.showForgotPasswordDialog = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
state.forgotPasswordLoading = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...toRefs(state),
|
...toRefs(state),
|
||||||
required,
|
required,
|
||||||
|
|
@ -218,7 +314,12 @@ export default {
|
||||||
checkCapslock,
|
checkCapslock,
|
||||||
getVertify,
|
getVertify,
|
||||||
startCountdown,
|
startCountdown,
|
||||||
resetCountdown
|
resetCountdown,
|
||||||
|
forgotPasswordFormRef,
|
||||||
|
getVerificationCode,
|
||||||
|
openForgotPasswordDialog,
|
||||||
|
handleForgotPassword,
|
||||||
|
pwdRule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue