feat: 修改密码

This commit is contained in:
cgd_mac 2022-02-24 17:43:57 +08:00
parent b24569fe4b
commit a0b23df39d
5 changed files with 341 additions and 24 deletions

View File

@ -1,6 +1,7 @@
import request from '@/utils/request' import request from '@/utils/request'
const mycourseApi = { const mycourseApi = {
changePassword: '/sys/user/changePwd',
mycourseList: 'myCourse/getMyCourseList', // 我的课程列表,课程搜索 mycourseList: 'myCourse/getMyCourseList', // 我的课程列表,课程搜索
addMyCourse: 'myCourse/addMyCourse', // 添加课程 addMyCourse: 'myCourse/addMyCourse', // 添加课程
centerList: 'focused/training/list', // 集中培训列表 centerList: 'focused/training/list', // 集中培训列表
@ -20,6 +21,14 @@ const mycourseApi = {
getMyCourseList: 'studyStatistics/getMyCourseList' // 课程学习统计 getMyCourseList: 'studyStatistics/getMyCourseList' // 课程学习统计
} }
export function reqChangePassword (data) {
return request({
url: mycourseApi.changePassword,
method: 'get',
params: data
})
}
export function reqCenterJoin (data) { export function reqCenterJoin (data) {
return request({ return request({
url: mycourseApi.centerJoin, url: mycourseApi.centerJoin,

View File

@ -1,12 +1,17 @@
<template> <template>
<a-dropdown v-if="currentUser && currentUser.name" placement="bottomRight"> <div>
<span class="ant-pro-account-avatar"> <a-dropdown v-if="currentUser && currentUser.name" placement="bottomRight">
<a-avatar size="small" src="https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png" class="antd-pro-global-header-index-avatar" /> <span class="ant-pro-account-avatar">
<span>{{ currentUser.name }}</span> <a-avatar
</span> size="small"
<template v-slot:overlay> src="https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png"
<a-menu class="ant-pro-drop-down menu" :selected-keys="[]"> class="antd-pro-global-header-index-avatar"
<!-- <a-menu-item v-if="menu" key="center" @click="handleToCenter"> />
<span>{{ currentUser.name }}</span>
</span>
<template v-slot:overlay>
<a-menu class="ant-pro-drop-down menu" :selected-keys="[]">
<!-- <a-menu-item v-if="menu" key="center" @click="handleToCenter">
<a-icon type="user" /> <a-icon type="user" />
个人中心 个人中心
</a-menu-item> </a-menu-item>
@ -15,23 +20,31 @@
个人设置 个人设置
</a-menu-item> </a-menu-item>
<a-menu-divider v-if="menu" />--> <a-menu-divider v-if="menu" />-->
<a-menu-item key="logout" @click="handleLogout"> <a-menu-item key="password" @click="handlerChangePassword">
<a-icon type="logout" /> <a-icon type="lock" />
退出登录 修改密码
</a-menu-item> </a-menu-item>
</a-menu> <a-menu-item key="logout" @click="handleLogout">
</template> <a-icon type="logout" />
</a-dropdown> 退出登录
<span v-else> </a-menu-item>
<a-spin size="small" :style="{ marginLeft: 8, marginRight: 8 }" /> </a-menu>
</span> </template>
</a-dropdown>
<span v-else>
<a-spin size="small" :style="{ marginLeft: 8, marginRight: 8 }" />
</span>
<ChangePassword ref="changePassword"></ChangePassword>
</div>
</template> </template>
<script> <script>
import { Modal } from 'ant-design-vue' import { Modal } from 'ant-design-vue'
import ChangePassword from '@/components/GlobalHeader/ChangePassword.vue'
export default { export default {
name: 'AvatarDropdown', name: 'AvatarDropdown',
components: { ChangePassword },
props: { props: {
currentUser: { currentUser: {
type: Object, type: Object,
@ -43,6 +56,10 @@ export default {
} }
}, },
methods: { methods: {
//
handlerChangePassword () {
this.$refs.changePassword.show()
},
handleToCenter () { handleToCenter () {
this.$router.push({ path: '/account/center' }) this.$router.push({ path: '/account/center' })
}, },
@ -54,14 +71,11 @@ export default {
title: this.$t('layouts.usermenu.dialog.title'), title: this.$t('layouts.usermenu.dialog.title'),
content: this.$t('layouts.usermenu.dialog.content'), content: this.$t('layouts.usermenu.dialog.content'),
onOk: () => { onOk: () => {
// return new Promise((resolve, reject) => {
// setTimeout(Math.random() > 0.5 ? resolve : reject, 1500)
// }).catch(() => console.log('Oops errors!'))
return this.$store.dispatch('Logout').then(() => { return this.$store.dispatch('Logout').then(() => {
this.$router.push({ name: 'login' }) this.$router.push({ name: 'login' })
}) })
}, },
onCancel () { } onCancel () {}
}) })
} }
} }

View File

@ -0,0 +1,280 @@
<!-- 作者cgd 邮箱349008059@qq.com 时间2022年02月24日 16:54:58 -->
<template>
<a-modal
title="修改密码"
:width="500"
v-model="visible"
:confirmLoading="confirmLoading"
:footer="null"
>
<a-form ref="formRegister" :form="form" id="formRegister">
<a-form-item>
<a-input
size="large"
type="text"
placeholder="用户名"
:value="$store.state.user.person.userName"
disabled
></a-input>
</a-form-item>
<a-form-item>
<a-input
size="large"
type="password"
placeholder="请输入密码"
v-decorator="[
'oldPassword',
{
rules: [{ required: true, message: '请输入密码' }],
validateTrigger: ['change', 'blur'],
},
]"
></a-input>
</a-form-item>
<a-popover
placement="rightTop"
:trigger="['focus', 'click']"
:getPopupContainer="trigger => trigger.parentElement"
v-model="state.passwordLevelChecked"
>
<template slot="content">
<div :style="{ width: '240px' }">
<div :class="['user-register', passwordLevelClass]">
强度
<span>{{ passwordLevelName }}</span>
</div>
<a-progress
:percent="state.percent"
:showInfo="false"
:strokeColor="passwordLevelColor"
/>
<div style="margin-top: 10px;">
<span>请输入至少包括大写小写数字特殊符号中的三种密码长度至少为8位</span>
</div>
</div>
</template>
<a-form-item>
<a-input-password
size="large"
@click="handlePasswordInputClick"
placeholder="请输入新密码"
v-decorator="[
'password',
{
rules: [
{
required: true,
message:
'请输入至少包括大写、小写、数字、特殊符号中的三种密码长度至少为8位。',
},
{ validator: this.handlePasswordLevel },
],
validateTrigger: ['change', 'blur'],
},
]"
></a-input-password>
</a-form-item>
</a-popover>
<a-form-item>
<a-input-password
size="large"
placeholder="请在此输入新的密码"
v-decorator="[
'password2',
{
rules: [
{
required: true,
message: '请输入至少包括大写、小写、数字、特殊符号中的三种密码长度至少为8位。',
},
{ validator: this.handlePasswordCheck },
],
validateTrigger: ['change', 'blur'],
},
]"
></a-input-password>
</a-form-item>
<a-form-item style="text-align: center;">
<a-button
:loading="btnLoading"
@click.stop.prevent="handleSubmit"
size="large"
type="primary"
htmlType="submit"
class="register-button"
>
修改密码
</a-button>
</a-form-item>
</a-form>
</a-modal>
</template>
<script>
const levelNames = {
0: '低',
1: '低',
2: '中',
3: '强',
4: '极强'
}
const levelClass = {
0: 'error',
1: 'error',
2: 'warning',
3: 'success'
}
const levelColor = {
0: '#ff0000',
1: '#ff0000',
2: '#ff7e05',
3: '#52c41a'
}
export default {
props: {},
data () {
return {
btnLoading: false,
form: this.$form.createForm(this),
state: {
time: 60,
smsSendBtn: false,
passwordLevel: 0,
passwordLevelChecked: false,
percent: 10,
progressColor: '#FF0000'
},
visible: false,
confirmLoading: false
}
},
computed: {
passwordLevelClass () {
return levelClass[this.state.passwordLevel]
},
passwordLevelName () {
return levelNames[this.state.passwordLevel]
},
passwordLevelColor () {
return levelColor[this.state.passwordLevel]
}
},
mounted () {},
methods: {
show () {
this.visible = true
},
handlePasswordLevel (rule, value, callback) {
let level = 0
//
if (/[0-9]/.test(value)) {
level++
}
if (/[a-z]/.test(value)) {
level++
}
if (/[A-Z]/.test(value)) {
level++
}
//
if (/[^0-9a-zA-Z]/.test(value)) {
level++
}
this.state.passwordLevel = level
this.state.percent = level * 25
if (level >= 3) {
if (level >= 4) {
this.state.percent = 100
}
callback()
} else {
if (level === 0) {
this.state.percent = 10
}
callback(new Error('密码强度不够'))
}
},
handlePasswordCheck (rule, value, callback) {
const password = this.form.getFieldValue('password')
console.log('value', value)
if (value === undefined) {
callback(new Error('请输入密码'))
}
if (value && password && value.trim() !== password.trim()) {
callback(new Error('两次密码不一致'))
}
callback()
},
handlePasswordInputClick () {
this.state.passwordLevelChecked = false
},
handleSubmit () {
const {
form: { validateFields },
state
} = this
validateFields({ force: true }, (err, values) => {
if (!err) {
this.btnLoading = true
state.passwordLevelChecked = false
this.$store.dispatch('ChangePassword', values).then(res => {
this.btnLoading = false
this.$message.success('修改密码成功')
this.$store.dispatch('Logout').then(() => {
this.$router.push({ name: 'login' })
})
})
}
})
}
}
}
</script>
<style lang="less">
.user-register {
&.error {
color: #ff0000;
}
&.warning {
color: #ff7e05;
}
&.success {
color: #52c41a;
}
}
.user-layout-register {
.ant-input-group-addon:first-child {
background-color: #fff;
}
}
</style>
<style lang="less" scoped>
.user-layout-register {
& > h3 {
font-size: 16px;
margin-bottom: 20px;
}
.getCaptcha {
display: block;
width: 100%;
height: 40px;
}
.register-button {
width: 100%;
text-align: center;
}
.login {
float: right;
line-height: 40px;
}
}
</style>

View File

@ -1,5 +1,6 @@
import storage from 'store' import storage from 'store'
import { login, getLoginUser, logout } from '@/api/login' import { login, getLoginUser, logout } from '@/api/login'
import { reqChangePassword } from '@/api/mycourse/index'
import { ACCESS_TOKEN } from '@/store/mutation-types' import { ACCESS_TOKEN } from '@/store/mutation-types'
import { welcome } from '@/utils/util' import { welcome } from '@/utils/util'
@ -81,7 +82,21 @@ const user = {
}) })
}) })
}, },
// 修改密码
ChangePassword ({ state }, data) {
return new Promise((resolve, reject) => {
try {
reqChangePassword({
oldPassword: data.oldPassword,
password: data.password
}).then(res => {
resolve(res)
})
} catch (error) {
reject(error)
}
})
},
// 登出 // 登出
Logout ({ commit, state }) { Logout ({ commit, state }) {
return new Promise(resolve => { return new Promise(resolve => {

View File

@ -116,7 +116,6 @@ export default {
data () { data () {
return { return {
form: this.$form.createForm(this), form: this.$form.createForm(this),
state: { state: {
time: 60, time: 60,
smsSendBtn: false, smsSendBtn: false,