This commit is contained in:
udf_admin@163.com
2020-05-05 12:10:19 +08:00
parent dc05c1d9d7
commit 4f7945b4e0
11 changed files with 245 additions and 34 deletions
+78 -19
View File
@@ -52,7 +52,7 @@
<div class="userPanel">
<el-row>
<el-col :span="24">
<el-avatar shape="square" size="small" icon="el-icon-user-solid" style="vertical-align: middle;">
<el-avatar :src="userDto.avatarFilePath" shape="square" size="small" icon="el-icon-user-solid" style="vertical-align: middle;">
</el-avatar>
<span>{{userDto.nickName}}</span>
<el-divider></el-divider>
@@ -60,14 +60,15 @@
</el-row>
<el-row>
<el-col :span="24">
<span><el-button type="text" :style="userDtoBtnStyle">个人中心</el-button></span>
<span><el-button type="text" :style="userDtoBtnStyle"
@click="userCenterBtnClick">个人中心</el-button></span>
<el-divider direction="vertical"></el-divider>
<span><el-button type="text" :style="logoutBtnStyle"
@click="logoutBtnClick">退出登录</el-button></span>
</el-col>
</el-row>
</div>
<el-avatar slot="reference" shape="square" size="large" icon="el-icon-user-solid">
<el-avatar :src="userDto.avatarFilePath" slot="reference" shape="square" size="large" icon="el-icon-user-solid">
</el-avatar>
</el-popover>
</div>
@@ -109,9 +110,9 @@
:show-close="false"
:visible.sync="leftMenuDrawerShow"
direction="ltr">
<div :style="leftMenuDrawerStyle">
<div :style="drawerStyle">
<el-scrollbar style="height:100%;">
<div class="leftMenuDrawerHeader">
<div class="drawerHeader">
<i class="el-icon-s-grid"></i>
<span slot="title">功能菜单</span>
<el-divider></el-divider>
@@ -120,6 +121,23 @@
</el-scrollbar>
</div>
</el-drawer>
<el-drawer
size="250px"
:with-header="false"
:show-close="false"
:visible.sync="rightUserCenterDrawerShow"
direction="rtl">
<div :style="drawerStyle">
<el-scrollbar style="height:100%;">
<div class="drawerHeader">
<i class="el-icon-s-grid"></i>
<span slot="title">个人中心</span>
<el-divider></el-divider>
</div>
<user-center ref="userCenter"></user-center>
</el-scrollbar>
</div>
</el-drawer>
</div>
</template>
@@ -128,10 +146,12 @@
import api_rbac from "./api/rbac";
import glob from "./assets/js/glob";
import leftMenu from "./components/leftMenu";
import userCenter from "./components/userCenter";
export default {
name: 'App',
components: {
userCenter,
leftMenu
},
data() {
@@ -186,7 +206,8 @@
menu: [],
elAsideShow: true,
leftMenuDrawerShow: false,
leftMenuDrawerStyle: {}
drawerStyle: {},
rightUserCenterDrawerShow: false
}
},
mounted() {
@@ -208,7 +229,6 @@
//主动调用一次resize监听
this.resizeListener();
//检查登陆
glob
glob.checkLogin();
//获得用户信息
const userDtoResponse = await api_rbac.infoByToken(glob.getToken());
@@ -238,7 +258,7 @@
this.appStyle.height = window.innerHeight + 'px';
this.mainElContainerStyle.height = window.innerHeight + 'px';
this.mainChildElContainerStyle.height = (window.innerHeight - 50) + 'px';
this.leftMenuDrawerStyle.height = window.innerHeight + 'px';
this.drawerStyle.height = window.innerHeight + 'px';
//设定框宽度
this.searchInputStyle.width = window.innerWidth - 200 - 10 + 'px';
//判断是否显示菜单栏
@@ -257,9 +277,16 @@
const loading = this.$loading({lock: true, text: '操作中'});
api_rbac.logout().then(response => window.location.href = '/').finally(() => loading.close());
},
//个人中心按钮点击事件
userCenterBtnClick() {
this.rightUserCenterDrawerShow = true;
this.$nextTick(() => {
this.$refs.userCenter.init();
});
},
//菜单按钮点击
mainMenuBtnClick() {
this.leftMenuDrawerShow = !this.leftMenuDrawerShow;
this.leftMenuDrawerShow = true;
}
}
}
@@ -268,6 +295,48 @@
.el-drawer {
background-color: #F5F5F5;
}
.drawerHeader {
padding: 10px 20px;
text-align: left;
font-size: 20px;
.el-divider--horizontal {
margin: 10px 0px 0px 0px;
}
}
.top-form {
.el-form {
.el-form-item {
margin-bottom: 0px !important;
label {
margin-bottom: 0px !important;
}
.el-form-item__label {
padding: 0 0 0px !important;
}
.el-button {
margin-top: 15px;
}
}
}
}
.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;
}
</style>
<style lang="scss" scoped>
.app {
@@ -434,14 +503,4 @@
padding-bottom: 0px;
}
}
.leftMenuDrawerHeader {
padding: 10px 20px;
text-align: left;
font-size: 20px;
.el-divider--horizontal {
margin: 10px 0px 0px 0px;
}
}
</style>
+4
View File
@@ -0,0 +1,4 @@
const api_file = {
upload: (formData = {}) => axios.post('/private/file/upload', formData, {'Content-Type': 'multipart/form-data'})
};
export default api_file;
+1
View File
@@ -1,5 +1,6 @@
const api_rbac = {
logout: () => axios.delete('/private/rbac/user/logout'),
save: (data = {}) => axios.put('/private/rbac/user/save', data),
infoByToken: (token = '') => axios.get('/private/rbac/user/info/by/token/' + token),
menu: () => axios.get('/private/rbac/menu')
};
+120
View File
@@ -0,0 +1,120 @@
<template>
<div class="userCenter top-form">
<el-form ref="form" :model="form" label-position="top" size="medium">
<el-form-item label="账号">
<el-input v-model="form.userId" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="昵称">
<el-input v-model="form.nickName"></el-input>
</el-form-item>
<el-form-item label="头像">
<el-upload
class="avatar-uploader"
action="''"
:show-file-list="false"
:before-upload="beforeAvatarFileUpload"
:http-request="avatarFileUpload">
<img v-if="form.avatarFilePath" :src="form.avatarFilePath" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
<el-form-item>
<el-button type="success" @click="saveBtnClick">保 存</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import api_rbac from "../api/rbac";
import glob from "../assets/js/glob";
import api_file from "../api/file";
export default {
name: "userCenter",
data() {
return {
elUserCenter: {},
form: {}
}
},
methods: {
//初始化
init() {
this.reset();
this.initAsync();
},
//初始化(异步)
async initAsync() {
//获得用户信息
const loading = this.$loading({target: this.elUserCenter, lock: true,});
api_rbac.infoByToken(glob.getToken()).then(response => {
this.form = response.data.result;
}).finally(() => loading.close());
},
//重置
reset() {
this.elUserCenter = document.getElementsByClassName('userCenter')[0];
this.form = {};
},
//保存按钮点击事件
saveBtnClick() {
//保存
const loading = this.$loading({target: this.elUserCenter, lock: true,});
api_rbac.save(this.form).then(response => {
window.location.href = `${process.env.VUE_APP_ADMIN_BASE_URL}`;
}).finally(() => loading.close());
},
//头像上传
beforeAvatarFileUpload(file) {
const isType = file.type === 'image/jpeg' || file.type === 'image/png';
const isSize = file.size / 1024 / 1024 < 1;
if (!isType) {
this.$message.error('上传头像图片只能是JPG/PNG格式!');
}
if (!isSize) {
this.$message.error('上传头像图片大小不能超过1MB!');
}
return isType && isSize;
},
//头像上传
avatarFileUpload(fileData) {
//构造参数
const data = new FormData()
data.append('rootPathCode', 'common');
data.append('file', fileData.file);
data.append('genPreviewPdfFile', false);
//上传
const loading = this.$loading({target: this.elUserCenter, lock: true,});
api_file.upload(data).then(response => {
const fileInfo = response.data.result;
this.form.avatarFileId = fileInfo.id;
this.form.avatarFilePath = '/file/' + fileInfo.rootPathCode + '/' + fileInfo.physicalRelativePath + '/' + fileInfo.physicalFileName;
}).finally(() => loading.close());
}
}
}
</script>
<style lang="scss" scoped>
.userCenter {
padding: 0px 20px;
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
}
.avatar {
width: 100px;
height: 100px;
display: block;
}
}
</style>
@@ -207,15 +207,15 @@ public class RbacService {
//判断
if (MapUtils.isEmpty(api)) {
log.warn("该用户无任何权限 : traceId -> {} , userId -> {} , URI -> {} , METHOD -> {}", CoreUtil.getTraceId(), userId, uri, method);
throw new ParameterValidException("无权限访问此接口");
throw new ParameterValidException("无请求权限");
}
if (!api.containsKey(uri)) {
log.warn("无URI权限 : traceId -> {} , userId -> {} , URI -> {} , METHOD -> {}", CoreUtil.getTraceId(), userId, uri, method);
throw new ParameterValidException("无权限访问此接口");
throw new ParameterValidException("无请求权限");
}
if (!api.get(uri).contains(method.toUpperCase())) {
log.warn("无METHOD权限 : traceId -> {} , userId -> {} , URI -> {} , METHOD -> {}", CoreUtil.getTraceId(), userId, uri, method);
throw new ParameterValidException("无权限访问此接口");
throw new ParameterValidException("无请求权限");
}
}
@@ -20,6 +20,8 @@ import org.itkk.udf.starter.cache.db.service.DbCacheService;
import org.itkk.udf.starter.core.CoreUtil;
import org.itkk.udf.starter.core.exception.ParameterValidException;
import org.itkk.udf.starter.core.id.IdWorker;
import org.itkk.udf.starter.file.db.dto.DbFileInfoDto;
import org.itkk.udf.starter.file.db.service.DbFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -54,6 +56,12 @@ public class UserService implements IUserService {
@Autowired
private DbCacheService dbCacheService;
/**
* dbFileService
*/
@Autowired
private DbFileService dbFileService;
/**
* 登陆
*
@@ -184,17 +192,18 @@ public class UserService implements IUserService {
* 用户信息更新
*
* @param userSaveDto userSaveDto
* @param token token
* @param userId userId
*/
@Transactional
public void save(UserSaveDto userSaveDto, String userId) {
public void save(UserSaveDto userSaveDto, String token, String userId) {
//获得用户信息
UserDto userDto = this.info(userSaveDto.getUserId());
//校验
if (userDto == null) {
throw new ParameterValidException("用户不存在");
}
if (iUserRepository.selectCount(new QueryWrapper<UserEntity>().lambda().eq(UserEntity::getNickName, userSaveDto.getNickName())) > 0) {
if (iUserRepository.selectCount(new QueryWrapper<UserEntity>().lambda().ne(UserEntity::getUserId, userDto.getUserId()).eq(UserEntity::getNickName, userSaveDto.getNickName())) > 0) {
throw new ParameterValidException("昵称已经存在,请重新输入");
}
//定义锁
@@ -210,6 +219,9 @@ public class UserService implements IUserService {
.set(UserEntity::getUpdateDate, new Date())
.eq(UserEntity::getUserId, userSaveDto.getUserId())
);
//淘汰缓存
final String cacheKey = "userDto_" + token;
cache.invalidate(cacheKey);
} finally {
//释放锁
dbCacheService.delete(key);
@@ -247,6 +259,13 @@ public class UserService implements IUserService {
userDto = new UserDto();
//转换
CoreUtil.copyPropertiesIgnoreNull(userEntity, userDto);
//获得头像路径
if (StringUtils.isNotBlank(userDto.getAvatarFileId())) {
DbFileInfoDto dbFileInfoDto = dbFileService.get(userDto.getAvatarFileId());
if (dbFileInfoDto != null) {
userDto.setAvatarFilePath("/file/" + dbFileInfoDto.getRootPathCode() + "/" + dbFileInfoDto.getPhysicalRelativePath() + "/" + dbFileInfoDto.getPhysicalFileName());
}
}
}
//返回
return userDto;
@@ -61,7 +61,7 @@ public class UserController {
*/
@PutMapping("save")
public RestResponse<String> save(@RequestBody @Valid UserSaveDto userSaveDto, String userId) {
userService.save(userSaveDto, CommonUtil.getUser(httpServletRequest).getUserId());
userService.save(userSaveDto, CommonUtil.getToken(httpServletRequest), CommonUtil.getUser(httpServletRequest).getUserId());
return RestResponse.success();
}
@@ -10,3 +10,11 @@ org.itkk.udf.api.rbac.api.menu.name=\u83DC\u5355
org.itkk.udf.api.rbac.api.menu.uri=/api/udf/web/private/rbac/menu
org.itkk.udf.api.rbac.api.menu.method=GET
#
org.itkk.udf.api.rbac.api.fileUpload.name=\u6587\u4EF6\u4E0A\u4F20
org.itkk.udf.api.rbac.api.fileUpload.uri=/api/udf/web/private/file/upload
org.itkk.udf.api.rbac.api.fileUpload.method=POST
#
org.itkk.udf.api.rbac.api.updateUser.name=\u66F4\u65B0\u7528\u6237\u4FE1\u606F
org.itkk.udf.api.rbac.api.updateUser.uri=/api/udf/web/private/rbac/user/save
org.itkk.udf.api.rbac.api.updateUser.method=PUT
#
@@ -1,3 +1,3 @@
org.itkk.udf.api.rbac.rolePublic.publicRole.name=\u516C\u5171\u89D2\u8272
org.itkk.udf.api.rbac.rolePublic.publicRole.apis=infoByToken,logout,menu
org.itkk.udf.api.rbac.rolePublic.publicRole.apis=infoByToken,logout,menu,fileUpload,updateUser
@@ -10,10 +10,10 @@ logging.file.name=d:/app/application-log/${spring.application.name}_${server.por
logging.file.max-size=100MB
logging.file.max-history=31
# FILE DB
com.imaxus.db.file.properties.mapping.public=D:/app/file/store/pubic/
com.imaxus.db.file.properties.mapping.temp=D:/app/file/store/temp/
com.imaxus.db.file.properties.fileUploadSupportType=pdf,jpg,jpeg,png
com.imaxus.db.file.properties.previewSupportContentType=application/pdf,image/jpeg,image/png
org.itkk.udf.starter.db.file.properties.mapping.common=D:/app/file/common/
org.itkk.udf.starter.db.file.properties.mapping.temp=D:/app/file/temp/
org.itkk.udf.starter.db.file.properties.fileUploadSupportType=pdf,jpg,jpeg,png
org.itkk.udf.starter.db.file.properties.previewSupportContentType=application/pdf,image/jpeg,image/png
# EXCEPTION
org.itkk.udf.starter.core.properties.outputExceptionStackTrace=true
# DataSource Dynamic
@@ -10,10 +10,10 @@ logging.file.name=/usr/local/share/app/application-log/${spring.application.name
logging.file.max-size=100MB
logging.file.max-history=31
# FILE DB
com.imaxus.db.file.properties.mapping.public=/usr/local/share/nginx/file/store/pubic/
com.imaxus.db.file.properties.mapping.temp=/usr/local/share/nginx/file/store/temp/
com.imaxus.db.file.properties.fileUploadSupportType=pdf,jpg,jpeg,png
com.imaxus.db.file.properties.previewSupportContentType=application/pdf,image/jpeg,image/png
org.itkk.udf.starter.db.file.properties.mapping.common=/usr/local/share/nginx/file/common/
org.itkk.udf.starter.db.file.properties.mapping.temp=/usr/local/share/nginx/file/temp/
org.itkk.udf.starter.db.file.properties.fileUploadSupportType=pdf,jpg,jpeg,png
org.itkk.udf.starter.db.file.properties.previewSupportContentType=application/pdf,image/jpeg,image/png
# EXCEPTION
org.itkk.udf.starter.core.properties.outputExceptionStackTrace=false
# DataSource Dynamic