<template>
<div class="container">
<div class="title">个人中心</div>
<div class="wrap">
<el-row>
<el-col :lg="16" :md="20" :sm="24" :xs="24">
<div class="user">
<div class="title">用户信息</div>
<div class="content">
<div class="name-wrapper">
<div class="label">昵称</div>
<div class="name">
<el-input
placeholder="请输入内容"
size="small"
v-model="nickname"
suffix-icon="el-icon-edit"
ref="input"
@blur="blur"
></el-input>
</div>
</div>
<div class="avatar" title="点击修改头像">
<img :src="user.avatar || defaultAvatar" alt="头像" />
<label class="mask">
<i class="iconfont icon-icon-test" style="font-size: 20px;"></i>
<input ref="avatarInput" type="file" accept="image/*" @change="fileChange" />
</label>
</div>
</div>
</div>
<div class="password">
<div class="title">修改密码</div>
<el-form
ref="form"
:model="form"
status-icon
:rules="rules"
@submit.prevent
label-width="90px"
label-position="left"
>
<el-form-item label="原始密码" prop="old_password">
<el-input type="password" v-model="form.old_password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="新密码" prop="new_password">
<el-input type="password" v-model="form.new_password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="confirm_password" label-position="top">
<el-input type="password" v-model="form.confirm_password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('form')">保存</el-button>
<el-button @click="resetForm('form')">重置</el-button>
</el-form-item>
</el-form>
</div>
</el-col>
</el-row>
</div>
<!-- 修改头像 -->
<avatar :originalImage="cropImg" :cropVisible="cropVisible" @switchCropVisible="switchCropVisible"></avatar>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import User from '@/lin/model/user'
import axios from '@/lin/plugin/axios'
import defaultAvatar from '@/assets/image/user/user.png'
import Avatar from '../../component/layout/avatar.vue'
export default {
name: 'Center',
components: { Avatar },
data() {
const oldPassword = (rule, value, callback) => {
if (!value) {
return callback(new Error('原始密码不能为空'))
}
callback()
}
const validatePassword = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
} else if (value.length < 6) {
callback(new Error('密码长度不能少于6位数'))
} else {
if (this.form.checkPassword !== '') {
this.$refs.form.validateField('confirm_password')
}
callback()
}
}
const validatePassword2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== this.form.new_password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
return {
cropImg: '',
username: null,
nickname: null,
defaultAvatar,
cropVisible: false,
form: {
old_password: '',
new_password: '',
confirm_password: '',
},
rules: {
old_password: [{ validator: oldPassword, trigger: 'blur', required: true }],
new_password: [{ validator: validatePassword, trigger: 'blur', required: true }],
confirm_password: [{ validator: validatePassword2, trigger: 'blur', required: true }],
},
}
},
computed: {
...mapGetters(['user']),
},
watch: {
cropVisible(val) {
if (!val) {
this.cropImg = ''
}
},
},
created() {
const { user } = this.$store.state
this.nickname = user?.nickname ? user.nickname : '佚名'
},
methods: {
...mapActions(['loginOut', 'setUserAndState']),
switchCropVisible(flag) {
this.cropVisible = flag
},
fileChange(event) {
if (event.target.files.length !== 1) {
return
}
const imgFile = event.target.files[0]
// 验证文件大小是否符合要求, 不大于 5M
if (imgFile.size > 1024 * 1024 * 5) {
this.$message.error('文件过大超过5M')
// 清空输入框
this.clearFileInput(this.$refs.avatarInput)
return
}
// 验证图像是否符合要求
const imgSrc = window.URL.createObjectURL(imgFile)
const image = new Image()
image.src = imgSrc
image.onload = () => {
const w = image.width
const h = image.height
if (w < 50) {
this.$message.error('图像宽度过小, 请选择大于50px的图像')
// 清空输入框
this.clearFileInput(this.$refs.avatarInput)
return
}
if (h < 50) {
this.$message.error('图像高度过小, 请选择大于50px的图像')
// 清空输入框
this.clearFileInput(this.$refs.avatarInput)
return
}
// 验证通过, 打开裁剪框
this.cropImg = imgSrc
this.cropVisible = true
if (this.$refs.croppa) {
this.$refs.croppa.refresh()
}
}
image.onerror = () => {
this.$message.error('获取本地图片出现错误, 请重试')
// 清空输入框
this.clearFileInput(this.$refs.avatarInput)
}
},
async blur() {
if (this.nickname) {
const { user } = this.$store.state
if (this.nickname !== user.nickname && this.nickname !== '佚名') {
axios({
method: 'put',
url: '/cms/user',
data: {
nickname: this.nickname,
},
showBackend: true,
})
.then(res => {
if (res.code < window.MAX_SUCCESS_CODE) {
this.$message({
type: 'success',
message: '更新昵称成功',
})
// 触发重新获取用户信息
return User.getInformation()
}
})
.then(res => {
// eslint-disable-line
this.setUserAndState(res)
this.nickname = res.nickname
})
}
}
this.nicknameChanged = false
},
submitForm(formName) {
if (this.form.old_password === '' && this.form.new_password === '' && this.form.confirm_password === '') {
this.dialogFormVisible = false
return
}
if (this.form.old_password === this.form.new_password) {
this.$message.error('新密码不能与原始密码一样')
return
}
this.$refs[formName].validate(async valid => {
// eslint-disable-line
if (valid) {
const res = await User.updatePassword(this.form)
if (res.code < window.MAX_SUCCESS_CODE) {
this.$message.success(`${res.message}`)
this.resetForm(formName)
this.dialogFormVisible = false
setTimeout(() => {
this.loginOut()
const { origin } = window.location
window.location.href = origin
}, 1000)
}
} else {
console.log('error submit!!')
this.$message.error('请填写正确的信息')
return false
}
})
},
// 重置表单
resetForm(formName) {
this.$refs[formName].resetFields()
},
clearFileInput(ele) {
ele.value = ''
},
},
}
</script>
<style lang="scss" scoped>
.container {
.title {
height: 59px;
line-height: 59px;
color: $parent-title-color;
font-size: 16px;
font-weight: 500;
text-indent: 40px;
border-bottom: 1px solid #dae1ec;
}
.wrap {
padding: 20px;
max-width: 800px;
.user {
padding: 0px 20px 25px 30px;
z-index: 100;
position: relative;
border-bottom: 1px solid #dae1ec;
.title {
font-weight: bold;
font-size: 16px;
color: #3a3a3a;
text-indent: 0px;
border: none;
}
.content {
display: flex;
justify-content: space-between;
align-items: center;
.name-wrapper {
display: flex;
align-items: center;
.label {
margin-right: 20px;
color: #333;
font-weight: bold;
font-size: 14px;
}
.name {
font-weight: 500;
}
}
.avatar {
width: 80px;
height: 80px;
border-radius: 50%;
cursor: pointer;
overflow: hidden;
position: relative;
.mask {
opacity: 0;
transition: all 0.2s;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
color: white;
input {
display: none;
}
}
&:hover {
.mask {
opacity: 1;
}
}
}
.text {
margin-left: 20px;
color: #fff;
display: flex;
flex-direction: column;
justify-content: center;
.username {
margin-bottom: 10px;
font-size: 16px;
cursor: pointer;
}
.desc {
font-size: 14px;
color: rgba(222, 226, 230, 1);
}
}
.info {
position: absolute;
bottom: 10px;
right: 10px;
display: flex;
color: #fff;
font-size: 14px;
height: 20px;
line-height: 20px;
.mid {
padding: 0 5px;
}
}
}
}
.password {
padding: 25px 20px 25px 30px;
.title {
color: #3a3a3a;
font-weight: bold;
font-size: 16px;
text-indent: 0px;
margin-bottom: 20px;
border: none;
}
}
}
}
</style>