Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
D
dataease
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
njgzx
dataease
Commits
fe29511e
提交
fe29511e
authored
5月 13, 2021
作者:
fit2cloud-chenyw
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 右上角功能菜单调整
上级
2f4842d4
隐藏空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
486 行增加
和
14 行删除
+486
-14
SysUserController.java
...in/java/io/dataease/controller/sys/SysUserController.java
+16
-0
SysUserService.java
...src/main/java/io/dataease/service/sys/SysUserService.java
+22
-8
user.js
frontend/src/api/system/user.js
+27
-1
zh.js
frontend/src/lang/zh.js
+1
-1
Topbar.vue
frontend/src/layout/components/Topbar.vue
+58
-4
topbar.scss
frontend/src/styles/topbar.scss
+8
-0
personPwd.vue
frontend/src/views/system/user/personPwd.vue
+88
-0
privateForm.vue
frontend/src/views/system/user/privateForm.vue
+266
-0
没有找到文件。
backend/src/main/java/io/dataease/controller/sys/SysUserController.java
浏览文件 @
fe29511e
...
...
@@ -3,6 +3,8 @@ package io.dataease.controller.sys;
import
com.github.pagehelper.Page
;
import
com.github.pagehelper.PageHelper
;
import
io.dataease.auth.api.dto.CurrentUserDto
;
import
io.dataease.commons.utils.AuthUtils
;
import
io.dataease.commons.utils.PageUtils
;
import
io.dataease.commons.utils.Pager
;
import
io.dataease.controller.sys.base.BaseGridRequest
;
...
...
@@ -73,4 +75,18 @@ public class SysUserController {
public
void
adminUpdatePwd
(
@RequestBody
SysUserPwdRequest
request
){
sysUserService
.
adminUpdatePwd
(
request
);
}
@ApiOperation
(
"个人信息"
)
@PostMapping
(
"/personInfo"
)
public
CurrentUserDto
personInfo
()
{
CurrentUserDto
user
=
AuthUtils
.
getUser
();
return
user
;
}
@ApiOperation
(
"更新个人信息"
)
@PostMapping
(
"/updatePersonInfo"
)
public
void
updatePersonInfo
(
@RequestBody
SysUserCreateRequest
request
){
sysUserService
.
updatePersonInfo
(
request
);
}
}
backend/src/main/java/io/dataease/service/sys/SysUserService.java
浏览文件 @
fe29511e
package
io
.
dataease
.
service
.
sys
;
import
io.dataease.auth.api.dto.CurrentUserDto
;
import
io.dataease.base.domain.SysUser
;
import
io.dataease.base.domain.SysUserExample
;
import
io.dataease.base.domain.SysUsersRolesExample
;
...
...
@@ -9,6 +10,7 @@ import io.dataease.base.mapper.SysUsersRolesMapper;
import
io.dataease.base.mapper.ext.ExtSysUserMapper
;
import
io.dataease.base.mapper.ext.query.GridExample
;
import
io.dataease.commons.constants.AuthConstants
;
import
io.dataease.commons.utils.AuthUtils
;
import
io.dataease.commons.utils.BeanUtils
;
import
io.dataease.commons.utils.CodingUtil
;
import
io.dataease.controller.sys.base.BaseGridRequest
;
...
...
@@ -89,6 +91,22 @@ public class SysUserService {
deleteUserRoles
(
user
.
getUserId
());
//先删除用户角色关联
saveUserRoles
(
user
.
getUserId
(),
request
.
getRoleIds
());
//再插入角色关联
return
sysUserMapper
.
updateByPrimaryKey
(
user
);
}
/**
* 用户修改个人信息
* @param request
* @return
*/
@CacheEvict
(
value
=
AuthConstants
.
USER_CACHE_NAME
,
key
=
"'user' + #request.userId"
)
@Transactional
public
int
updatePersonInfo
(
SysUserCreateRequest
request
){
SysUser
user
=
BeanUtils
.
copyBean
(
new
SysUser
(),
request
);
long
now
=
System
.
currentTimeMillis
();
user
.
setUpdateTime
(
now
);
return
sysUserMapper
.
updateByPrimaryKeySelective
(
user
);
}
...
...
@@ -107,20 +125,16 @@ public class SysUserService {
*/
@CacheEvict
(
value
=
AuthConstants
.
USER_CACHE_NAME
,
key
=
"'user' + #request.userId"
)
public
int
updatePwd
(
SysUserPwdRequest
request
)
{
if
(!
StringUtils
.
equals
(
request
.
getPassword
(),
request
.
getRepeatPassword
())){
throw
new
RuntimeException
(
"两次密码不一致"
);
}
SysUser
temp
=
new
SysUser
();
temp
.
setUserId
(
request
.
getUserId
());
SysUser
user
=
findOne
(
temp
);
CurrentUserDto
user
=
AuthUtils
.
getUser
();
if
(
ObjectUtils
.
isEmpty
(
user
))
{
throw
new
RuntimeException
(
"用户不存在"
);
}
if
(!
StringUtils
.
equals
(
request
.
getPassword
(
),
user
.
getPassword
())){
if
(!
StringUtils
.
equals
(
CodingUtil
.
md5
(
request
.
getPassword
()
),
user
.
getPassword
())){
throw
new
RuntimeException
(
"密码错误"
);
}
SysUser
sysUser
=
new
SysUser
();
sysUser
.
setUserId
(
request
.
getUserId
());
sysUser
.
setUserId
(
user
.
getUserId
());
sysUser
.
setPassword
(
CodingUtil
.
md5
(
request
.
getNewPassword
()));
return
sysUserMapper
.
updateByPrimaryKeySelective
(
sysUser
);
}
...
...
frontend/src/api/system/user.js
浏览文件 @
fe29511e
import
request
from
'@/utils/request'
const
pathMap
=
{
userUpdatePwdPath
:
'/api/user/updatePwd/'
,
personInfoPath
:
'/api/user/personInfo/'
,
piupdatePath
:
'/api/user/updatePersonInfo/'
,
queryPath
:
'/api/user/userGrid/'
,
deletePath
:
'/api/user/delete/'
,
createPath
:
'/api/user/create'
,
...
...
@@ -55,4 +58,27 @@ export const editStatus = (data) => {
})
}
export
default
{
editPassword
,
delUser
,
editUser
,
addUser
,
userLists
,
editStatus
}
export
const
persionInfo
=
()
=>
{
return
request
({
url
:
pathMap
.
personInfoPath
,
method
:
'post'
})
}
export
const
updatePerson
=
(
data
)
=>
{
return
request
({
url
:
pathMap
.
piupdatePath
,
method
:
'post'
,
data
})
}
export
const
updatePersonPwd
=
(
data
)
=>
{
return
request
({
url
:
pathMap
.
userUpdatePwdPath
,
method
:
'post'
,
data
})
}
export
default
{
editPassword
,
delUser
,
editUser
,
addUser
,
userLists
,
editStatus
,
persionInfo
,
updatePerson
,
updatePersonPwd
}
frontend/src/lang/zh.js
浏览文件 @
fe29511e
...
...
@@ -406,7 +406,7 @@ export default {
special_characters_are_not_supported
:
'不支持特殊字符'
,
mobile_number_format_is_incorrect
:
'手机号码格式不正确'
,
email_format_is_incorrect
:
'邮箱格式不正确'
,
password_format_is_incorrect
:
'有效密码:
8
-30位,英文大小写字母+数字+特殊字符(可选)'
,
password_format_is_incorrect
:
'有效密码:
6
-30位,英文大小写字母+数字+特殊字符(可选)'
,
old_password
:
'旧密码'
,
new_password
:
'新密码'
,
repeat_password
:
'确认密码'
,
...
...
frontend/src/layout/components/Topbar.vue
浏览文件 @
fe29511e
...
...
@@ -37,9 +37,46 @@
<lang-select
class=
"right-menu-item hover-effect"
/>
</
template
>
<el-dropdown
class=
"avatar-container"
trigger=
"click"
>
<el-dropdown
class=
"top-dropdown"
>
<span
class=
"el-dropdown-link"
>
{{ name }}
<i
class=
"el-icon-arrow-down el-icon--right"
/>
</span>
<el-dropdown-menu
slot=
"dropdown"
>
<router-link
to=
"/person-info/index"
>
<el-dropdown-item>
个人信息
</el-dropdown-item>
</router-link>
<router-link
to=
"/person-pwd/index"
>
<el-dropdown-item>
重置密码
</el-dropdown-item>
</router-link>
<a
href=
"https://panjiachen.github.io/vue-element-admin-site/#/"
target=
"_blank"
>
<el-dropdown-item>
Docs
</el-dropdown-item>
</a>
<a
href=
"https://fit2cloud.com/"
target=
"_blank"
>
<el-dropdown-item>
关于
</el-dropdown-item>
</a>
<el-dropdown-item
divided
@
click
.
native=
"logout"
>
<span
style=
"display:block;"
>
退出
</span>
</el-dropdown-item>
<!-- <el-dropdown-item>黄金糕</el-dropdown-item>
<el-dropdown-item>狮子头</el-dropdown-item>
<el-dropdown-item>螺蛳粉</el-dropdown-item>
<el-dropdown-item disabled>双皮奶</el-dropdown-item>
<el-dropdown-item divided>蚵仔煎</el-dropdown-item> -->
</el-dropdown-menu>
</el-dropdown>
<!-- <el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper">
<img
src=
"@/assets/avatar.jpeg"
class=
"user-avatar"
>
<div class="de-user-avatar">
<span>
{{ name }}
</span>
</div>
</div>
<el-dropdown-menu slot="dropdown" class="user-dropdown">
<router-link to="/">
...
...
@@ -55,7 +92,7 @@
<span style="display:block;">Log Out</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-dropdown>
-->
</div>
</div>
</template>
...
...
@@ -113,7 +150,8 @@ export default {
},
...
mapGetters
([
'avatar'
,
'permission_routes'
'permission_routes'
,
'name'
])
},
...
...
@@ -222,5 +260,21 @@ export default {
}
</
script
>
<
style
lang=
"scss"
scoped
>
.el-dropdown-link
{
cursor
:
pointer
;
color
:
#ffffff
;
}
.el-icon-arrow-down
{
font-size
:
12px
;
}
.top-dropdown
{
display
:
inline-block
;
padding
:
10px
8px
;
height
:
100%
;
font-size
:
16px
;
color
:
rgba
(
255
,
255
,
255
,.
87
);
vertical-align
:
text-bottom
;
margin-right
:
30px
;
}
</
style
>
frontend/src/styles/topbar.scss
浏览文件 @
fe29511e
...
...
@@ -87,6 +87,14 @@
height
:
40px
;
border-radius
:
10px
;
}
.de-user-avatar
{
cursor
:
pointer
;
height
:
40px
;
border-radius
:
10px
;
span
{
color
:
#ffffff
;
}
}
.el-icon-caret-bottom
{
cursor
:
pointer
;
...
...
frontend/src/views/system/user/personPwd.vue
0 → 100644
浏览文件 @
fe29511e
<
template
>
<layout-content
header=
"修改密码"
>
<el-form
ref=
"createUserForm"
:model=
"form"
:rules=
"rule"
size=
"small"
label-width=
"auto"
label-position=
"right"
>
<el-form-item
label=
"原始密码"
prop=
"oldPwd"
>
<el-input
v-model=
"form.oldPwd"
type=
"password"
/>
</el-form-item>
<el-form-item
label=
"新密码"
prop=
"newPwd"
>
<el-input
v-model=
"form.newPwd"
type=
"password"
/>
</el-form-item>
<el-form-item
label=
"确认密码"
prop=
"repeatPwd"
>
<el-input
v-model=
"form.repeatPwd"
type=
"password"
/>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
@
click=
"save"
>
保存
</el-button>
</el-form-item>
</el-form>
</layout-content>
</
template
>
<
script
>
import
LayoutContent
from
'@/components/business/LayoutContent'
import
{
updatePersonPwd
}
from
'@/api/system/user'
export
default
{
components
:
{
LayoutContent
},
data
()
{
return
{
form
:
{
},
rule
:
{
oldPwd
:
[
{
required
:
true
,
message
:
this
.
$t
(
'user.input_password'
),
trigger
:
'blur'
}
// {
// required: true,
// pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{6,30}$/,
// message: this.$t('member.password_format_is_incorrect'),
// trigger: 'blur'
// }
],
newPwd
:
[
{
required
:
true
,
message
:
this
.
$t
(
'user.input_password'
),
trigger
:
'blur'
}
],
repeatPwd
:
[
{
required
:
true
,
message
:
this
.
$t
(
'user.input_password'
),
trigger
:
'blur'
},
{
required
:
true
,
trigger
:
'blur'
,
validator
:
this
.
repeatValidator
}
]
}
}
},
created
()
{
},
methods
:
{
repeatValidator
(
rule
,
value
,
callback
)
{
if
(
value
!==
this
.
form
.
newPwd
)
{
callback
(
new
Error
(
this
.
$t
(
'member.inconsistent_passwords'
)))
}
else
{
callback
()
}
},
save
()
{
this
.
$refs
.
createUserForm
.
validate
(
valid
=>
{
if
(
valid
)
{
const
param
=
{
password
:
this
.
form
.
oldPwd
,
newPassword
:
this
.
form
.
newPwd
}
updatePersonPwd
(
param
).
then
(
res
=>
{
this
.
$success
(
this
.
$t
(
'commons.save_success'
))
this
.
$router
.
push
(
'/panel/index'
)
})
}
else
{
return
false
}
})
}
}
}
</
script
>
frontend/src/views/system/user/privateForm.vue
0 → 100644
浏览文件 @
fe29511e
<
template
>
<layout-content
header=
"个人信息"
>
<div>
<el-form
ref=
"createUserForm"
:disabled=
"formType !== 'modify'"
:model=
"form"
:rules=
"rule"
size=
"small"
label-width=
"auto"
label-position=
"right"
>
<el-form-item
label=
"用户名"
prop=
"username"
>
<el-input
v-model=
"form.username"
disabled
/>
</el-form-item>
<el-form-item
label=
"电话"
prop=
"phone"
>
<el-input
v-model=
"form.phone"
/>
</el-form-item>
<el-form-item
label=
"昵称"
prop=
"nickName"
>
<el-input
v-model=
"form.nickName"
/>
</el-form-item>
<el-form-item
label=
"邮箱"
prop=
"email"
>
<el-input
v-model=
"form.email"
/>
</el-form-item>
<!--
<el-form-item
label=
"性别"
>
<el-radio-group
v-model=
"form.gender"
style=
"width: 178px"
>
<el-radio
label=
"男"
>
男
</el-radio>
<el-radio
label=
"女"
>
女
</el-radio>
</el-radio-group>
</el-form-item>
-->
<el-form-item
label=
"状态"
>
<el-radio-group
v-model=
"form.enabled"
disabled
style=
"width: 140px"
>
<el-radio
:label=
"1"
>
启用
</el-radio>
<el-radio
:label=
"0"
>
停用
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
disabled
label=
"部门"
prop=
"dept"
>
<treeselect
v-model=
"form.deptId"
disabled
:options=
"depts"
:load-options=
"loadDepts"
:auto-load-root-options=
"false"
placeholder=
"选择部门"
/>
</el-form-item>
<el-form-item
label=
"角色"
prop=
"roleIds"
>
<el-select
v-model=
"form.roleIds"
disabled
style=
"width: 100%"
multiple
placeholder=
"请选择"
@
remove-tag=
"deleteTag"
@
change=
"changeRole"
>
<el-option
v-for=
"item in roles"
:key=
"item.name"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<!--
<el-form-item>
<el-button
v-if=
"formType==='modify'"
type=
"primary"
@
click=
"save"
>
保存
</el-button>
<el-button
v-if=
"formType==='modify'"
@
click=
"reset"
>
重置
</el-button>
</el-form-item>
-->
</el-form>
<div
slot=
"footer"
style=
"margin-left: 30px;"
class=
"dialog-footer"
>
<el-button
v-if=
"formType==='modify'"
type=
"text"
@
click=
"reset"
>
{{
$t
(
'commons.cancel'
)
}}
</el-button>
<el-button
v-if=
"formType==='modify'"
type=
"primary"
@
click=
"save"
>
确认
</el-button>
<el-button
v-if=
"formType!=='modify'"
type=
"primary"
@
click=
"edit"
>
编辑
</el-button>
</div>
</div>
</layout-content>
</
template
>
<
script
>
import
LayoutContent
from
'@/components/business/LayoutContent'
import
Treeselect
from
'@riophae/vue-treeselect'
import
'@riophae/vue-treeselect/dist/vue-treeselect.css'
import
{
PHONE_REGEX
}
from
'@/utils/validate'
import
{
LOAD_CHILDREN_OPTIONS
,
LOAD_ROOT_OPTIONS
}
from
'@riophae/vue-treeselect'
import
{
getDeptTree
,
treeByDeptId
}
from
'@/api/system/dept'
import
{
allRoles
}
from
'@/api/system/role'
import
{
updatePerson
,
persionInfo
}
from
'@/api/system/user'
export
default
{
components
:
{
LayoutContent
,
Treeselect
},
data
()
{
return
{
form
:
{
roles
:
[{
id
:
''
}]
},
rule
:
{
username
:
[
{
required
:
true
,
message
:
this
.
$t
(
'user.input_id'
),
trigger
:
'blur'
},
{
min
:
1
,
max
:
50
,
message
:
this
.
$t
(
'commons.input_limit'
,
[
1
,
50
]),
trigger
:
'blur'
},
{
required
:
true
,
pattern
:
'^[^
\
u4e00-
\
u9fa5]+$'
,
message
:
this
.
$t
(
'user.special_characters_are_not_supported'
),
trigger
:
'blur'
}
],
nickName
:
[
{
required
:
true
,
message
:
this
.
$t
(
'user.input_name'
),
trigger
:
'blur'
},
{
min
:
2
,
max
:
50
,
message
:
this
.
$t
(
'commons.input_limit'
,
[
2
,
50
]),
trigger
:
'blur'
},
{
required
:
true
,
message
:
this
.
$t
(
'user.special_characters_are_not_supported'
),
trigger
:
'blur'
}
],
phone
:
[
{
pattern
:
PHONE_REGEX
,
message
:
this
.
$t
(
'user.mobile_number_format_is_incorrect'
),
trigger
:
'blur'
}
],
email
:
[
{
required
:
true
,
message
:
this
.
$t
(
'user.input_email'
),
trigger
:
'blur'
},
{
required
:
true
,
pattern
:
/^
[
a-zA-Z0-9_._-
]
+@
[
a-zA-Z0-9_-
]
+
(\.[
a-zA-Z0-9_-
]
+
)
+$/
,
message
:
this
.
$t
(
'user.email_format_is_incorrect'
),
trigger
:
'blur'
}
],
password
:
[
{
required
:
true
,
message
:
this
.
$t
(
'user.input_password'
),
trigger
:
'blur'
},
{
required
:
true
,
pattern
:
/^
(?=
.*
[
a-z
])(?=
.*
[
A-Z
])(?=
.*
\d)[^]{8,30}
$/
,
message
:
this
.
$t
(
'member.password_format_is_incorrect'
),
trigger
:
'blur'
}
],
newPassword
:
[
{
required
:
true
,
message
:
this
.
$t
(
'user.input_password'
),
trigger
:
'blur'
},
{
required
:
true
,
pattern
:
/^
(?=
.*
[
a-z
])(?=
.*
[
A-Z
])(?=
.*
\d)[^]{8,30}
$/
,
message
:
this
.
$t
(
'member.password_format_is_incorrect'
),
trigger
:
'blur'
}
],
roleIds
:
[{
required
:
true
,
message
:
this
.
$t
(
'user.input_roles'
),
trigger
:
'change'
}]
},
defaultForm
:
{
id
:
null
,
username
:
null
,
nickName
:
null
,
gender
:
'男'
,
email
:
null
,
enabled
:
1
,
deptId
:
null
,
phone
:
null
,
roleIds
:
[]
},
depts
:
null
,
roles
:
[],
roleDatas
:
[],
userRoles
:
[],
formType
:
'add'
}
},
created
()
{
this
.
queryPerson
()
this
.
initRoles
()
},
methods
:
{
queryPerson
()
{
persionInfo
().
then
(
res
=>
{
const
info
=
res
.
data
this
.
form
=
info
const
roles
=
info
.
roles
this
.
form
[
'roleIds'
]
=
roles
.
map
(
role
=>
role
.
id
)
if
(
this
.
form
.
deptId
===
0
)
{
this
.
form
.
deptId
=
null
}
this
.
initDeptTree
()
})
},
edit
()
{
this
.
formType
=
'modify'
},
initRoles
()
{
allRoles
().
then
(
res
=>
{
this
.
roles
=
res
.
data
})
},
initDeptTree
()
{
treeByDeptId
(
this
.
form
.
deptId
||
0
).
then
(
res
=>
{
const
results
=
res
.
data
.
map
(
node
=>
{
if
(
node
.
hasChildren
&&
!
node
.
children
)
{
node
.
children
=
null
// delete node.children
}
return
node
})
this
.
depts
=
results
})
},
// 获取弹窗内部门数据
loadDepts
({
action
,
parentNode
,
callback
})
{
if
(
action
===
LOAD_ROOT_OPTIONS
&&
!
this
.
form
.
deptId
)
{
const
_self
=
this
treeByDeptId
(
0
).
then
(
res
=>
{
const
results
=
res
.
data
.
map
(
node
=>
{
if
(
node
.
hasChildren
&&
!
node
.
children
)
{
node
.
children
=
null
}
return
node
})
_self
.
depts
=
results
callback
()
})
}
if
(
action
===
LOAD_CHILDREN_OPTIONS
)
{
const
_self
=
this
getDeptTree
(
parentNode
.
id
).
then
(
res
=>
{
parentNode
.
children
=
res
.
data
.
map
(
function
(
obj
)
{
return
_self
.
normalizer
(
obj
)
})
callback
()
})
}
},
normalizer
(
node
)
{
if
(
node
.
hasChildren
)
{
node
.
children
=
null
}
return
{
id
:
node
.
deptId
,
label
:
node
.
name
,
children
:
node
.
children
}
},
deleteTag
(
value
)
{
this
.
userRoles
.
forEach
(
function
(
data
,
index
)
{
if
(
data
.
id
===
value
)
{
this
.
userRoles
.
splice
(
index
,
value
)
}
}.
bind
(
this
))
},
changeRole
(
value
)
{
this
.
userRoles
=
[]
value
.
forEach
(
function
(
data
,
index
)
{
const
role
=
{
id
:
data
}
this
.
userRoles
.
push
(
role
)
}.
bind
(
this
))
},
reset
()
{
this
.
formType
=
'add'
this
.
queryPerson
()
},
save
()
{
this
.
$refs
.
createUserForm
.
validate
(
valid
=>
{
if
(
valid
)
{
updatePerson
(
this
.
form
).
then
(
res
=>
{
this
.
$success
(
this
.
$t
(
'commons.save_success'
))
this
.
reset
()
})
}
else
{
return
false
}
})
}
}
}
</
script
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论