diff --git a/components.d.ts b/components.d.ts index e472236..df6e3ab 100644 --- a/components.d.ts +++ b/components.d.ts @@ -26,6 +26,9 @@ declare module 'vue' { ASwitch: typeof import('ant-design-vue/es')['Switch'] ATextarea: typeof import('ant-design-vue/es')['Textarea'] 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'] Empty: typeof import('./src/components/empty/Empty.vue')['default'] ImageCropper: typeof import('./src/components/image-cropper/index.vue')['default'] diff --git a/src/services/index.js b/src/services/index.js index a15deb8..29d69b8 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -21,12 +21,12 @@ export function logout() { } export function getConfig(params) { return request.get('/sms/v1/logo', { - params: wrapperParams(params), + params: wrapperParams(params) }) } export function getDict(data) { return request.get('/dict/children', { - params: wrapperParams(data), + params: wrapperParams(data) }) } export function getSysconf() { @@ -48,7 +48,7 @@ export function getPortal(params) { } export function getServiceQuota(tenantId, data) { return request.get(`/cos/v1/tenants/${tenantId}/quotas`, { - params: wrapperParams(data), + params: wrapperParams(data) }) } export function replaceToken(params) { @@ -69,7 +69,7 @@ export function getSystemTreeConfigs(params) { // 更新系统配置信息 export function updateSystemConfigs(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) { return request.post('/sms/v1/users/code', wrapperParams(params)) } + +// 忘记密码 +export function forgetPassword(params) { + return request.post('/sms/v1/users/forget', params) +} diff --git a/src/views/login/login.vue b/src/views/login/login.vue index 8b04ee4..c1d4563 100644 --- a/src/views/login/login.vue +++ b/src/views/login/login.vue @@ -42,13 +42,42 @@ 记住密码 - {{ configs.helpInformationContent }} + {{ configs.helpInformationContent }} + 忘记密码 登录 + + + + + + + + + + + + + +
+ + + {{ codeCountdown > 0 ? `${codeCountdown}s后重新获取` : '获取验证码' }} + +
+
+
+ +
@@ -61,8 +90,8 @@ import { useStore } from 'vuex' import { useRouter, useRoute } from 'vue-router' import setLoginData from './tools' import { required } from '@/validate' -import { getVertifyCode } from '@/services' -import { message } from 'ant-design-vue' +import { getVertifyCode, forgetPassword } from '@/services' +import { message, Modal } from 'ant-design-vue' export default { components: { UserOutlined, LockOutlined }, @@ -78,11 +107,23 @@ export default { verifyLoading: false, countdown: 0, isCountingDown: false, - needSmsVerify: true + needSmsVerify: true, + showForgotPasswordDialog: false, + forgotPasswordForm: { + account: '', + password: '', + confirmPassword: '', + verificationCode: '' + }, + forgotPasswordLoading: false, + codeCountdown: 0, + codeLoading: false }) const store = useStore() + const pwdRule = computed(() => store.state.app.systemConfig.pwdStrength + ',pswNoSpace' + ',required') const configs = computed(() => store.getters.pageConfig) const loginFormRef = ref(null) + const forgotPasswordFormRef = ref(null) let countdownTimer = null // 开始倒计时 @@ -122,12 +163,15 @@ export default { const route = useRoute() // 监听account变化,如果清空则重置needSmsVerify - watch(() => state.loginForm.account, (newAccount) => { - if (!newAccount.trim()) { - state.needSmsVerify = true - resetCountdown() // 同时重置倒计时 + watch( + () => state.loginForm.account, + (newAccount) => { + if (!newAccount.trim()) { + state.needSmsVerify = true + resetCountdown() // 同时重置倒计时 + } } - }) + ) const getVertify = () => { if (state.isCountingDown) return // 如果正在倒计时,不允许重复点击 @@ -209,6 +253,58 @@ export default { 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 { ...toRefs(state), required, @@ -218,7 +314,12 @@ export default { checkCapslock, getVertify, startCountdown, - resetCountdown + resetCountdown, + forgotPasswordFormRef, + getVerificationCode, + openForgotPasswordDialog, + handleForgotPassword, + pwdRule } } }