提示:这里可以主体参考elementplus官网的Layout布局实现https://element-plus.gitee.io/zh-CN/component/layout.html
<template>
<div class="app-container">
<el-row :gutter="20">
<el-col :span="6">
<el-card class="box-card">
<template v-slot:header>
<div class="clearfix">
<span>个人信息</span>
</div>
</template>
<div>
<div class="text-center">
<avatar :user="currentUser"/>
</div>
<ul class="list-group list-group-striped">
<li class="list-group-item">
<svg-icon icon="user" /> 用户名称
<div class="pull-right">{{currentUser.username}}</div>
</li>
<li class="list-group-item">
<svg-icon icon="phone" /> 手机号码
<div class="pull-right">{{currentUser.phonenumber}}</div>
</li>
<li class="list-group-item">
<svg-icon icon="email" /> 用户邮箱
<div class="pull-right">{{currentUser.email}}</div>
</li>
<li class="list-group-item">
<svg-icon icon="peoples" /> 所属角色
<div class="pull-right">{{currentUser.roles}}</div>
</li>
<li class="list-group-item">
<svg-icon icon="date" /> 创建日期
<div class="pull-right">{{formatDate(currentUser.loginDate)}}</div>
</li>
</ul>
</div>
</el-card>
</el-col>
<el-col :span="18">
<el-card>
<template v-slot:header>
<div class="clearfix">
<span>基本资料</span>
</div>
</template>
<el-tabs v-model="activeTab">
<el-tab-pane label="基本资料" name="userinfo">
基本资料信息
</el-tab-pane>
<el-tab-pane label="修改密码" name="resetPwd">
修改密码信息
</el-tab-pane>
</el-tabs>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup>
import {ref} from 'vue'
import store from '@/store'
import { formatDate } from '@/util/formatDate.js'
const currentUser = ref(store.getters.GET_USERINFO);
const activeTab = ref("userinfo");
</script>
<style lang="scss" scoped>
.list-group-striped>.list-group-item {
border-left: 0;
border-right: 0;
border-radius: 0;
padding-left: 0;
padding-right: 0;
}
.list-group-item {
border-bottom: 1px solid #e7eaec;
border-top: 1px solid #e7eaec;
margin-bottom: -1px;
padding: 11px 0;
font-size: 13px;
}
.pull-right{
float: right!important;
}
::v-deep .el-card__body{
height:230px;
}
::v-deep .box-card{
height:450px;
}
</style>
//方法一
export function formatDate(val) {
var date = new Date(Number(val)); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
var Y = date.getFullYear() + "-";
var M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
var D = date.getDate() + " ";
var h = date.getHours() + ":";
var m = date.getMinutes() + ":";
var s = (date.getSeconds() < 10 ? "0" + (date.getSeconds()) : date.getSeconds());
return Y + M + D + h + m + s;
}
时间处理解析有很多的方式,按照你喜欢的方式使用即可!!!
<template>
<el-form ref="userRef" :model="form" :rules="rules" label-width="100px" >
<el-form-item label="手机号码:" prop="phonenumber">
<el-input v-model="form.phonenumber" maxlength="11" />
</el-form-item>
<el-form-item label="用户邮箱:" prop="email">
<el-input v-model="form.email" maxlength="50" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">保存</el-button>
</el-form-item>
</el-form>
</template>
<script setup>
import {defineProps, ref} from "vue";
import requestUtil from "@/util/request";
import { ElMessage } from 'element-plus'
import store from "@/store";
const props=defineProps(
{
user:{
type:Object,
default:()=>{},
required:true
}
}
)
const form=ref({
id:-1,
phonenumber:'',
email:''
})
const userRef=ref(null)
const rules = ref({
email: [{ required: true, message: "邮箱地址不能为空", trigger: "blur" }, { type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
phonenumber: [{ required: true, message: "手机号码不能为空", trigger: "blur" }, { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }],
});
form.value=props.user;
如果之前已经在controller包中编写过SysUserController的需要注意,那么重命名,要么处理一下即可
<template>
<el-form ref="userRef" :model="form" :rules="rules" label-width="100px" >
<el-form-item label="手机号码:" prop="phonenumber">
<el-input v-model="form.phonenumber" maxlength="11" />
</el-form-item>
<el-form-item label="用户邮箱:" prop="email">
<el-input v-model="form.email" maxlength="50" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">保存</el-button>
</el-form-item>
</el-form>
</template>
<script setup>
import {defineProps, ref} from "vue";
import requestUtil from "@/util/request";
import { ElMessage } from 'element-plus'
import store from "@/store";
const props=defineProps(
{
user:{
type:Object,
default:()=>{},
required:true
}
}
)
const form=ref({
id:-1,
phonenumber:'',
email:''
})
const userRef=ref(null)
const rules = ref({
email: [{ required: true, message: "邮箱地址不能为空", trigger: "blur" }, { type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
phonenumber: [{ required: true, message: "手机号码不能为空", trigger: "blur" }, { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }],
});
form.value=props.user;
const handleSubmit=()=>{
userRef.value.validate(async (valid)=>{
if(valid) {
let result = await requestUtil.post("sys/user/save", form.value);
let data = result.data;
if (data.code == 200) {
ElMessage.success("执行成功!")
store.commit("SET_USERINFO", form.value)
}
}
})
}
</script>
<style lang="scss" scoped>
</style>
@RestController
@RequestMapping("/sys/user")
public class SysUsersController {
@Autowired
private SysUserService sysUserService;
/**
* 添加或者修改
* @param sysUser
* @return
*/
@PostMapping("/save")
@PreAuthorize("hasAuthority('system:user:add')"+"||"+"hasAuthority('system:user:edit')")
public ResponseData save(@RequestBody SysUser sysUser){
if(sysUser.getId()==null || sysUser.getId()==-1){
}else{
//此处修改更新时间可以使用MybatisPlus中的自动填充策略去实现【解决硬编码问题】
sysUser.setUpdateTime(new Date());
sysUserService.updateById(sysUser);
}
return new ResponseData("操作成功",200);
}
}
<template>
<el-form ref="pwdRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="旧密码" prop="oldPassword">
<el-input v-model="form.oldPassword" placeholder="请输入旧密码" type="password" show-password />
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input v-model="form.newPassword" placeholder="请输入新密码" type="password" show-password />
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="form.confirmPassword" placeholder="请确认密码" type="password" show-password/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">保存</el-button>
</el-form-item>
</el-form>
</template>
<script setup>
import {defineProps, ref} from "vue";
import requestUtil from "@/util/request";
import { ElMessage } from 'element-plus'
import store from "@/store";
const props=defineProps(
{
user:{
type:Object,
default:()=>{},
required:true
}
}
)
const form=ref({
id:-1,
oldPassword:'',
newPassword:'',
confirmPassword:''
})
const pwdRef=ref(null)
form.value=props.user;
const equalToPassword = (rule, value, callback) => {
if (form.value.newPassword !== value) {
callback(new Error("两次输入的密码不一致"));
} else {
callback();
}
};
const rules = ref({
oldPassword: [{ required: true, message: "旧密码不能为空", trigger: "blur" }],
newPassword: [{ required: true, message: "新密码不能为空", trigger: "blur" }, { min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }],
confirmPassword: [{ required: true, message: "确认密码不能为空", trigger: "blur" }, { required: true, validator: equalToPassword, trigger: "blur" }]
});
const handleSubmit=()=>{
pwdRef.value.validate(async (valid)=>{
if(valid) {
let result = await requestUtil.post("sys/user/updateUserPwd", form.value);
let data = result.data;
if (data.code == 200) {
ElMessage.success("密码修改成功,下一次登录生效!")
store.commit("SET_USERINFO", form.value)
}else{
ElMessage.error(data.msg)
}
}
})
}
</script>
<style lang="scss" scoped>
</style>
<template>
<el-form ref="pwdRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="旧密码" prop="oldPassword">
<el-input v-model="form.oldPassword" placeholder="请输入旧密码" type="password" show-password />
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input v-model="form.newPassword" placeholder="请输入新密码" type="password" show-password />
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="form.confirmPassword" placeholder="请确认密码" type="password" show-password/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">保存</el-button>
</el-form-item>
</el-form>
</template>
<script setup>
import {defineProps, ref} from "vue";
import requestUtil from "@/util/request";
import { ElMessage } from 'element-plus'
import store from "@/store";
const props=defineProps(
{
user:{
type:Object,
default:()=>{},
required:true
}
}
)
const form=ref({
id:-1,
oldPassword:'',
newPassword:'',
confirmPassword:''
})
const pwdRef=ref(null)
form.value=props.user;
const equalToPassword = (rule, value, callback) => {
if (form.value.newPassword !== value) {
callback(new Error("两次输入的密码不一致"));
} else {
callback();
}
};
const rules = ref({
oldPassword: [{ required: true, message: "旧密码不能为空", trigger: "blur" }],
newPassword: [{ required: true, message: "新密码不能为空", trigger: "blur" }, { min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" }],
confirmPassword: [{ required: true, message: "确认密码不能为空", trigger: "blur" }, { required: true, validator: equalToPassword, trigger: "blur" }]
});
const handleSubmit=()=>{
pwdRef.value.validate(async (valid)=>{
if(valid) {
let result = await requestUtil.post("sys/user/updateUserPwd", form.value);
let data = result.data;
if (data.code == 200) {
ElMessage.success("密码修改成功,下一次登录生效!")
store.commit("SET_USERINFO", form.value)
}else{
ElMessage.error(data.msg)
}
}
})
}
</script>
<style lang="scss" scoped>
</style>
@RestController
@RequestMapping("/sys/user")
public class SysUsersController {
@Autowired
private SysUserService sysUserService;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
/**
* 修改密码
* @param sysUser
* @return
*/
@PostMapping("/updateUserPwd")
@PreAuthorize("hasAuthority('system:user:edit')")
public ResponseData updateUserPwd(@RequestBody SysUser sysUser){
SysUser currentUser = sysUserService.getById(sysUser.getId());
if(bCryptPasswordEncoder.matches(sysUser.getOldPassword(),currentUser.getPassword())){
currentUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getNewPassword()));
currentUser.setUpdateTime(new Date());
sysUserService.updateById(currentUser);
return new ResponseData("操作成功",200);
}else{
return new ResponseData("输入原密码错误!",500);
}
}
}
参考官网的示例去实现
https://element-plus.gitee.io/zh-CN/component/upload.html#%E7%94%A8%E6%88%B7%E5%A4%B4%E5%83%8F
1、:headers="headers"需要在请求的时候携带好token值
2、:action="getServerUrl()+‘sys/user/uploadImage’"后端的请求资源路径
3、:on-success="handleAvatarSuccess"成功的回调函数
4、:before-upload="beforeAvatarUpload"上传之前的回调函数
<template>
<el-form
ref="formRef"
:model="form"
label-width="100px"
style="text-align: center;padding-bottom:10px"
>
<el-upload
:headers="headers"
class="avatar-uploader"
:action="getServerUrl()+'sys/user/uploadImage'"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
<el-button @click="handleConfirm" >确认更换</el-button>
</el-form>
</template>
<script setup>
import {defineProps, ref} from "vue";
import requestUtil,{getServerUrl} from "@/util/request";
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import store from "@/store";
const props=defineProps(
{
user:{
type:Object,
default:()=>{},
required:true
}
}
)
const headers=ref({
token:store.getters.GET_TOKEN
})
const form=ref({
id:-1,
avatar:''
})
const formRef=ref(null)
const imageUrl=ref("")
form.value=props.user;
imageUrl.value=getServerUrl()+'image/userAvatar/'+form.value.avatar
const handleAvatarSuccess=(res)=>{
imageUrl.value=getServerUrl()+res.data.src
form.value.avatar=res.data.title;
}
const beforeAvatarUpload = (file) => {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
ElMessage.error('图片必须是jpg格式')
}
if (!isLt2M) {
ElMessage.error('图片大小不能超过2M!')
}
return isJPG && isLt2M
}
const handleConfirm=async()=>{
let result=await requestUtil.post("sys/user/updateAvatar",form.value);
let data=result.data;
if(data.code==200){
ElMessage.success("执行成功!")
store.commit("SET_USERINFO",form.value)
}else{
ElMessage.error(data.msg);
}
}
</script>
<style>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar {
width: 120px;
height: 120px;
display: block;
}
</style>
package com.xuguoguo.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期工具类
* @author xuguoguo
*
*/
public class DateUtil {
/**
* 日期对象转字符串
* @param date
* @param format
* @return
*/
public static String formatDate(Date date,String format){
String result="";
SimpleDateFormat sdf=new SimpleDateFormat(format);
if(date!=null){
result=sdf.format(date);
}
return result;
}
/**
* 字符串转日期对象
* @param str
* @param format
* @return
* @throws Exception
*/
public static Date formatString(String str,String format) throws Exception{
if(StringUtil.isEmpty(str)){
return null;
}
SimpleDateFormat sdf=new SimpleDateFormat(format);
return sdf.parse(str);
}
public static String getCurrentDateStr(){
Date date=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddhhmmssSSSSSSSSS");
return sdf.format(date);
}
public static String getCurrentDatePath()throws Exception{
Date date=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd/");
return sdf.format(date);
}
public static void main(String[] args) {
try {
System.out.println(getCurrentDateStr());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
<template>
<el-form
ref="formRef"
:model="form"
label-width="100px"
style="text-align: center;padding-bottom:10px"
>
<el-upload
:headers="headers"
class="avatar-uploader"
:action="getServerUrl()+'sys/user/uploadImage'"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
<el-button @click="handleConfirm" >确认更换</el-button>
</el-form>
</template>
<script setup>
import {defineProps, ref} from "vue";
import requestUtil,{getServerUrl} from "@/util/request";
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import store from "@/store";
const props=defineProps(
{
user:{
type:Object,
default:()=>{},
required:true
}
}
)
const headers=ref({
token:store.getters.GET_TOKEN
})
const form=ref({
id:-1,
avatar:''
})
const formRef=ref(null)
const imageUrl=ref("")
form.value=props.user;
imageUrl.value=getServerUrl()+'image/userAvatar/'+form.value.avatar
const handleAvatarSuccess=(res)=>{
imageUrl.value=getServerUrl()+res.data.src
form.value.avatar=res.data.title;
}
const beforeAvatarUpload = (file) => {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
ElMessage.error('图片必须是jpg格式')
}
if (!isLt2M) {
ElMessage.error('图片大小不能超过2M!')
}
return isJPG && isLt2M
}
const handleConfirm=async()=>{
let result=await requestUtil.post("sys/user/updateAvatar",form.value);
let data=result.data;
if(data.code==200){
ElMessage.success("执行成功!")
store.commit("SET_USERINFO",form.value)
}else{
ElMessage.error(data.msg);
}
}
</script>
<style>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar {
width: 120px;
height: 120px;
display: block;
}
</style>
@RestController
@RequestMapping("/sys/user")
public class SysUsersController {
@Autowired
private SysUserService sysUserService;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Value("${avatarImagesFilePath}")
private String avatarImagesFilePath;
/**
* 上传用户头像图片
* @param file
* @return
* @throws Exception
*/
@RequestMapping("/uploadImage")
@PreAuthorize("hasAuthority('system:user:edit')")
public Map<String,Object> uploadImage(MultipartFile file)throws Exception{
Map<String,Object> resultMap=new HashMap<>();
if(!file.isEmpty()){
// 获取文件名
String originalFilename = file.getOriginalFilename();
String suffixName=originalFilename.substring(originalFilename.lastIndexOf("."));
//防止重复的文件名[使用时间或者uuid之类的唯一值处理即可]
String newFileName= DateUtil.getCurrentDateStr()+suffixName;
FileUtils.copyInputStreamToFile(file.getInputStream(),new File(avatarImagesFilePath+newFileName));
resultMap.put("code",0);
resultMap.put("msg","上传成功");
Map<String,Object> dataMap=new HashMap<>();
dataMap.put("title",newFileName);
dataMap.put("src","image/userAvatar/"+newFileName);
resultMap.put("data",dataMap);
}
return resultMap;
}
/**
* 修改用户头像
* @param sysUser
* @return
*/
@RequestMapping("/updateAvatar")
@PreAuthorize("hasAuthority('system:user:edit')")
public ResponseData updateAvatar(@RequestBody SysUser sysUser){
SysUser currentUser = sysUserService.getById(sysUser.getId());
currentUser.setUpdateTime(new Date());
currentUser.setAvatar(sysUser.getAvatar());
sysUserService.updateById(currentUser);
return new ResponseData("操作成功",200);
}
}
提示:本小结主体写的是个人中心、修改密码以及用户头像三个功能模块细化成前端的不同组件来实现的基本流程摘录,也是每个后台必有得功能哦!!!
本章的第八小节完毕,敬请期待后续更新(可留言需要学习哪方面的内容哈)!如果需要源码或者工具的朋友们可关注微信公众号"锅锅编程生活"或者扫描二维码关注回复关键字/后台留言获取即可!