新增 切换部门功能、多部门岗位权限

This commit is contained in:
thinkgem
2025-02-01 16:22:15 +08:00
parent b12c010cd3
commit 4de0934e7f
10 changed files with 144 additions and 38 deletions

View File

@@ -54,8 +54,11 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
public static final String MESSAGE_PARAM = "message"; // 登录返回消息
public static final String REMEMBER_USERCODE_PARAM = "rememberUserCode"; // 记住用户名
public static final String EXCEPTION_ATTRIBUTE_NAME = "exception"; // 异常类属性名
public static final String LOGIN_PARAM = "__login"; // 支持GET方式登录的参数
public static final String LOGIN_PARAM = "__login"; // 支持GET方式登录的参数
public static final Boolean POST_ROLE_PERMI = Global.getConfigToBoolean("user.postRolePermi", "false");
public static final Boolean SWITCH_OFFICE = Global.getConfigToBoolean("user.switchOffice", "false");
private static final Logger logger = LoggerFactory.getLogger(FormFilter.class);
private static FormFilter instance;
@@ -477,9 +480,9 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
}
}
data.put("roleList", roleList);
List<Map<String, Object>> postList = ListUtils.newArrayList();
if (Global.getConfigToBoolean("user.postRolePermi", "false")
&& User.USER_TYPE_EMPLOYEE.equals(user.getUserType())) {
if (POST_ROLE_PERMI && User.USER_TYPE_EMPLOYEE.equals(user.getUserType())) {
List<Map<String, Object>> postList = ListUtils.newArrayList();
data.put("postRolePermi", "true");
Employee employee = user.getRefObj();
for (EmployeePost ep : EmpUtils.getEmployeePostList(employee.getEmpCode())){
Post post = ep.getPost();
@@ -490,8 +493,13 @@ public class FormFilter extends org.apache.shiro.web.filter.authc.FormAuthentica
postList.add(postMap);
}
}
data.put("postList", postList);
}
if (SWITCH_OFFICE && User.USER_TYPE_EMPLOYEE.equals(user.getUserType())) {
data.put("switchOffice", "true");
data.put("officeCode", EmpUtils.getCurrentOfficeCode());
data.put("officeName", EmpUtils.getCurrentOfficeName());
}
data.put("postList", postList);
data.put("desktopUrl", desktopUrl != null ? desktopUrl : Global.getConfig("sys.index.desktopUrl"));
return data;
}

View File

@@ -8,6 +8,7 @@ import com.alibaba.fastjson.JSONValidator;
import com.jeesite.common.codec.EncodeUtils;
import com.jeesite.common.collect.ListUtils;
import com.jeesite.common.collect.MapUtils;
import com.jeesite.common.collect.SetUtils;
import com.jeesite.common.config.Global;
import com.jeesite.common.entity.Page;
import com.jeesite.common.lang.DateUtils;
@@ -18,6 +19,7 @@ import com.jeesite.common.shiro.realm.AuthorizingRealm;
import com.jeesite.common.utils.excel.ExcelExport;
import com.jeesite.common.utils.excel.annotation.ExcelField.Type;
import com.jeesite.common.web.BaseController;
import com.jeesite.common.web.http.ServletUtils;
import com.jeesite.modules.sys.entity.*;
import com.jeesite.modules.sys.service.*;
import com.jeesite.modules.sys.utils.EmpUtils;
@@ -29,6 +31,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -41,7 +44,8 @@ import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
* 员工用户Controller
@@ -446,41 +450,89 @@ public class EmpUserController extends BaseController {
}
/**
* 获取当前用户附属部门
* @return
* 获取当前用户部门(包括附属部门) v5.10.1
*/
@RequiresPermissions("user")
@RequestMapping(value = "officeListData")
@ResponseBody
public List<EmployeeOffice> officeListData () {
Employee employee = EmpUtils.getEmployee();
return employeeService.findEmployeeOfficeList(employee);
public List<EmployeeOffice> officeListData() {
Office office = EmpUtils.getOffice();
EmployeeOffice employeeOffice = new EmployeeOffice();
employeeOffice.setOfficeCode(office.getOfficeCode());
employeeOffice.setViewCode(office.getViewCode());
employeeOffice.setOfficeName(office.getOfficeName());
employeeOffice.setFullName(office.getFullName());
employeeOffice.setTreeNames(office.getTreeNames());
List<EmployeeOffice> list = ListUtils.newArrayList(employeeOffice);
list.addAll(EmpUtils.getEmployeeOfficeList());
return list;
}
/**
* 切换当前用户到附属部门
* @param officeCode
* @return
* 切换部门菜单(用户->部门(含附属部门)->岗位->角色v5.10.1
*/
@RequiresPermissions("user")
@RequestMapping(value = "switchOffice/{officeCode}")
@ResponseBody
public String switchOffice(@PathVariable String officeCode) {
if (StringUtils.equals(officeCode, "default")) {
@RequestMapping(value = {"switchOffice","switchOffice/{officeCode}"})
public String switchOffice(@PathVariable(required=false) String officeCode, HttpServletRequest request, HttpServletResponse response) {
Session session = UserUtils.getSession();
Set<String> postCodes = SetUtils.newHashSet();
if (StringUtils.isNotBlank(officeCode)){
// 查询用户关联的岗位
AtomicReference<String> officeCodeRef = new AtomicReference<>();
AtomicReference<String> officeNameRef = new AtomicReference<>();
// 如果是当前用户主部门
Office office = EmpUtils.getOffice();
EmpUtils.setCurrentOffice(office.getOfficeCode(), office.getOfficeName());
return renderResult(Global.TRUE, text("部门切换成功!"));
}
List<EmployeeOffice> employeeOfficeList = EmpUtils.getEmployeeOfficeList().stream()
.filter(e -> StringUtils.equals(e.getOfficeCode(), officeCode)).collect(Collectors.toList());
if (!employeeOfficeList.isEmpty()) {
EmployeeOffice office = employeeOfficeList.get(0);
EmpUtils.setCurrentOffice(office.getOfficeCode(), office.getOfficeName());
return renderResult(Global.TRUE, text("部门切换成功!"));
if (StringUtils.equals(officeCode, office.getOfficeCode())) {
officeCodeRef.set(office.getOfficeCode());
officeNameRef.set(StringUtils.defaultIfBlank(office.getFullName(), office.getOfficeName()));
EmpUtils.getEmployeePostList().forEach(ep -> {
postCodes.add(ep.getPostCode());
});
}
// 如果是当前用户的附属部门
else {
EmpUtils.getEmployeeOfficeList().forEach(eo -> {
if (StringUtils.equals(officeCode, eo.getOfficeCode())) {
officeCodeRef.set(eo.getOfficeCode());
officeNameRef.set(StringUtils.defaultIfBlank(eo.getFullName(), eo.getOfficeName()));
postCodes.add(eo.getPostCode());
}
});
}
// 如果匹配不到,有权限切换的部门,则给于提示
if (StringUtils.isAnyBlank(officeCodeRef.get(), officeNameRef.get())) {
return renderResult(response, Global.FALSE, text("没有权限切换到该部门"));
}
EmpUtils.setCurrentOffice(session, officeCodeRef.get(), officeNameRef.get());
} else {
return renderResult(Global.FALSE, text("部门切换失败,所切换部门不是您的附属部门!"));
EmpUtils.removeCurrentOffice(session);
}
// 开启 user.postRolePermi 参数后,就可以使用岗位关联角色过滤菜单权限
if (Global.getConfigToBoolean("user.postRolePermi", "false")) {
if (!postCodes.isEmpty()) {
// 查询并设置岗位关联的角色
PostRole where = new PostRole();
where.setPostCode_in(postCodes.toArray(new String[0]));
where.sqlMap().loadJoinTableAlias("r");
List<String> roleCodes = ListUtils.newArrayList();
postService.findPostRoleList(where).forEach(e -> {
if (e.getRole() != null && PostRole.STATUS_NORMAL.equals(e.getRole().getStatus())) {
roleCodes.add(e.getRoleCode());
}
});
if (roleCodes.isEmpty()){
roleCodes.add("__none__");
}
session.setAttribute("roleCode", StringUtils.joinComma(roleCodes)); // 5.4.0+ 支持多个,逗号隔开
} else {
session.removeAttribute("roleCode");
}
}
UserUtils.removeCache(UserUtils.CACHE_AUTH_INFO+"_"+session.getId());
if (ServletUtils.isAjaxRequest(request)) {
return renderResult(response, Global.TRUE, text("部门切换成功"));
}
return REDIRECT + adminPath + "/index";
}
}

View File

@@ -150,8 +150,11 @@ user:
# 二级管理员的控制权限类型1拥有的权限 2管理的权限管理功能包括用户管理、组织机构、公司管理等v4.1.5+
adminCtrlPermi: 2
# 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理
# 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理 v5.9.2
postRolePermi: false
# 是否启用切换部门功能,再开启启用岗位角色后可支持 用户->附属部门->岗位->关联角色,纳入菜单和权限管理 v5.10.1
switchOffice: false
# 多租户模式SAAS模式专业版
useCorpModel: false

View File

@@ -10,6 +10,7 @@
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<% include('/include/sysIndex/topMenuCorp.html'){} %>
<% include('/include/sysIndex/topMenuOffice.html'){} %>
<li><a href="javascript:" id="fullScreen" title="${text('全屏')}" data-placement="bottom" data-container="body"><i class="fa fa-arrows-alt"></i></a></li>
<li><a href="javascript:" id="switchSkin" title="${text('切换主题')}" style="margin-top:-1px;" data-placement="bottom" data-container="body" data-layer-width="600" data-layer-height="350"><i class="fa fa-dashboard"></i></a></li>
<% include('/include/sysIndex/topMenuLang.html'){} %>

View File

@@ -1,7 +1,7 @@
<% if(@Global.getConfigToBoolean('user.useCorpModel', 'false') && hasPermi('sys:corpAdmin:edit')){ %>
<li>
<a href="javascript:" id="switchCorp">
<i class="fa icon-home"></i> ${text('当前租户')}(${session.corpCode}) ${session.corpName}
<i class="fa icon-home"></i> ${text('当前租户')}${currentCorpName}
</a>
<div class="hide"><#form:treeselect id="switchCorpSelect" title="${text('租户切换')}" allowClear="false"
url="${ctx}/sys/corpAdmin/treeData?isShowCode=true" callbackFuncName="switchCorpSelectCallback"/>

View File

@@ -0,0 +1,27 @@
<% if(toBoolean(switchOffice!)){ %>
<li>
<a href="javascript:" id="switchOffice">
<i class="fa icon-grid" style="font-size:12px;"></i> ${officeName!}
</a>
<div class="hide"><#form:treeselect id="switchOfficeSelect" title="${text('部门切换')}" allowClear="false"
url="${ctx}/sys/empUser/officeListData?isShowCode=true" callbackFuncName="switchOfficeSelectCallback"
fieldNames="{'id':'officeCode','name':'fullName'}"/>
</div>
<script>
$('#switchOffice').click(function(){
$('#switchOfficeSelectButton').click();
});
function switchOfficeSelectCallback(id, act, index, layero, nodes){
if (act == 'ok'){
var officeCode = $('#switchOfficeSelectCode').val();
if (officeCode != ''){
js.ajaxSubmit("${ctx}/sys/empUser/switchOffice/"+officeCode, function(data){
js.showMessage(data.message);
js.window.location.reload();
});
}
}
}
</script>
</li>
<% } %>

View File

@@ -47,7 +47,7 @@
<% }else{ %>
<li class="mt10"></li>
<% } %>
<% if(postList.~size > 0){ %>
<% if(toBoolean(postRolePermi!) && postList.~size > 0){ %>
<li class="divider"></li>
<% var postCode = @ObjectUtils.toStringIgnoreNull(session.postCode, ''); %>
<li class="dropdown-header mb5">${text('选择岗位')}<% if(isNotBlank(postCode)){ %>

View File

@@ -303,9 +303,12 @@ spring:
# maxPoolSize: 20
# keepAliveSeconds: 60
# 日志配置
# 日志配置fatal、error、warn、info、debug
logging:
config: classpath:config/logback-spring.xml
# level:
# root: warn
# com.jeesite: debug
#======================================#
#========== System settings ===========#
@@ -350,8 +353,11 @@ user:
# # 二级管理员的控制权限类型1拥有的权限 2管理的权限管理功能包括用户管理、组织机构、公司管理等v4.1.5+
# adminCtrlPermi: 2
#
# # 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理
# # 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理 v5.9.2
# postRolePermi: false
#
# # 是否启用切换部门功能,再开启启用岗位角色后可支持 用户->附属部门->岗位->关联角色,纳入菜单和权限管理 v5.10.1
# switchOffice: false
# 多租户模式SAAS模式专业版
useCorpModel: false

View File

@@ -99,9 +99,12 @@ spring:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
# 日志配置
# 日志配置fatal、error、warn、info、debug
logging:
config: classpath:config/logback-spring.xml
# level:
# root: warn
# com.jeesite: debug
#======================================#
#========== System settings ===========#

View File

@@ -303,9 +303,12 @@ spring:
# maxPoolSize: 20
# keepAliveSeconds: 60
# 日志配置
# 日志配置fatal、error、warn、info、debug
logging:
config: classpath:config/logback-spring.xml
# level:
# root: warn
# com.jeesite: debug
#======================================#
#========== System settings ===========#
@@ -350,8 +353,11 @@ user:
# # 二级管理员的控制权限类型1拥有的权限 2管理的权限管理功能包括用户管理、组织机构、公司管理等v4.1.5+
# adminCtrlPermi: 2
#
# # 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理
# # 是否启用岗位角色,开启后将 用户->岗位->关联角色,纳入菜单和权限管理 v5.9.2
# postRolePermi: false
#
# # 是否启用切换部门功能,再开启启用岗位角色后可支持 用户->附属部门->岗位->关联角色,纳入菜单和权限管理 v5.10.1
# switchOffice: false
# 多租户模式SAAS模式专业版
useCorpModel: false