✨ 组织树独立权限、平台公司回写、合同计费客商角色与查看菜单补齐
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+6
-2
@@ -126,8 +126,11 @@ public class DeptController extends BladeController {
|
||||
|
||||
/**
|
||||
* 获取部门树形结构
|
||||
* <p>
|
||||
* 登录即可调用;数据范围由角色「数据权限」中 {@code dept_tree}(树形结构)单独配置,
|
||||
* 未配置时返回空树(默认不展示)。
|
||||
*/
|
||||
@PreAuth(menu = "dept")
|
||||
@PreAuth(AuthConstant.PERMIT_ALL)
|
||||
@GetMapping("/tree")
|
||||
@ApiOperationSupport(order = 4)
|
||||
@Operation(summary = "树形结构", description = "树形结构")
|
||||
@@ -139,8 +142,9 @@ public class DeptController extends BladeController {
|
||||
* 懒加载获取部门树形结构
|
||||
* <p>
|
||||
* tenantId 由 Service 层完整决策:超管入参为空表示查全部,非超管强制覆盖为会话租户。
|
||||
* 数据范围与 {@link #tree} 相同,由 {@code dept_tree} 单独配置,未配置时返回空树。
|
||||
*/
|
||||
@PreAuth(menu = "dept")
|
||||
@PreAuth(AuthConstant.PERMIT_ALL)
|
||||
@GetMapping("/lazy-tree")
|
||||
@ApiOperationSupport(order = 5)
|
||||
@Operation(summary = "懒加载树形结构", description = "树形结构")
|
||||
|
||||
+10
@@ -66,6 +66,16 @@ public interface IRoleMenuDataScopeService extends BaseService<RoleMenuDataScope
|
||||
*/
|
||||
RoleDataScopeVO resolveByMenuCode(List<Long> roleIds, String menuCode, List<Long> userDeptIds);
|
||||
|
||||
/**
|
||||
* 按菜单编码解析角色数据权限;菜单不存在或未配置时返回空权限(不回落为全部组织)
|
||||
*
|
||||
* @param roleIds 角色ID集合
|
||||
* @param menuCode 菜单编码
|
||||
* @param userDeptIds 用户所属组织
|
||||
* @return 解析结果
|
||||
*/
|
||||
RoleDataScopeVO resolveByMenuCodeOrEmpty(List<Long> roleIds, String menuCode, List<Long> userDeptIds);
|
||||
|
||||
/**
|
||||
* 合并用户全部角色菜单配置为最宽数据权限
|
||||
*
|
||||
|
||||
+35
-35
@@ -224,13 +224,18 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 组织树专用数据权限菜单编码(角色「数据权限」中单独配置;未配置时组织树默认不展示)。
|
||||
*/
|
||||
public static final String MENU_DEPT_TREE = "dept_tree";
|
||||
|
||||
/**
|
||||
* 解析当前登录用户的组织树数据权限。
|
||||
* <p>
|
||||
* 超管或角色菜单数据权限最宽合并为「全部组织」时不过滤;
|
||||
* 其余按角色配置的组织并集过滤。仅「本人创建」时按用户所属组织及下级展示组织树。
|
||||
* 仅读取 {@link #MENU_DEPT_TREE}「树形结构」菜单的数据权限配置,不再合并其他业务菜单;
|
||||
* 超管不过滤;未配置该菜单数据权限时返回空树(默认不显示)。
|
||||
*
|
||||
* @return 过滤上下文;无法识别用户时按空权限处理
|
||||
* @return 过滤上下文;无法识别用户或未配置时按空权限处理
|
||||
*/
|
||||
private DeptDataScopeFilter resolveDeptDataScopeFilter() {
|
||||
if (AuthUtil.isAdministrator()) {
|
||||
@@ -246,8 +251,11 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
if (Func.isNotEmpty(user) && Func.isNotEmpty(user.getDeptId())) {
|
||||
userDeptIds = Func.toLongList(user.getDeptId());
|
||||
}
|
||||
RoleDataScopeVO scope = roleMenuDataScopeService.resolveWidest(roleIds, userDeptIds);
|
||||
if (scope == null || scope.isAllDept()) {
|
||||
RoleDataScopeVO scope = roleMenuDataScopeService.resolveByMenuCodeOrEmpty(roleIds, MENU_DEPT_TREE, userDeptIds);
|
||||
if (scope == null) {
|
||||
return DeptDataScopeFilter.empty();
|
||||
}
|
||||
if (scope.isAllDept()) {
|
||||
return DeptDataScopeFilter.all();
|
||||
}
|
||||
LinkedHashSet<Long> allowedDeptIds = new LinkedHashSet<>();
|
||||
@@ -665,12 +673,9 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
dept.setAncestors(parent.getAncestors() + StringPool.COMMA + dept.getParentId());
|
||||
}
|
||||
dept.setIsDeleted(BladeConstant.DB_NOT_DELETED);
|
||||
if (dept.getIsPlatformCompany() == null) {
|
||||
dept.setIsPlatformCompany(0);
|
||||
}
|
||||
if (dept.getIsBusinessDept() == null) {
|
||||
dept.setIsBusinessDept(0);
|
||||
}
|
||||
// 统一规范为 0/1,避免前端传空串、布尔或其它类型导致更新未生效
|
||||
dept.setIsPlatformCompany(normalizeYesNoFlag(dept.getIsPlatformCompany()));
|
||||
dept.setIsBusinessDept(normalizeYesNoFlag(dept.getIsBusinessDept()));
|
||||
// 排序未填时默认 1
|
||||
if (dept.getSort() == null) {
|
||||
dept.setSort(1);
|
||||
@@ -679,9 +684,24 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
throw new ServiceException("租户ID不能为空");
|
||||
}
|
||||
validateDeptCategory(dept);
|
||||
validateDeptCode(dept, parent);
|
||||
validateDeptCode(dept);
|
||||
validateContractInitialSerial(dept);
|
||||
return saveOrUpdate(dept);
|
||||
boolean saved = saveOrUpdate(dept);
|
||||
if (saved && Func.isNotEmpty(dept.getId())) {
|
||||
// 显式回写两个业务标志,避免部分更新路径漏改
|
||||
this.update(Wrappers.<Dept>lambdaUpdate()
|
||||
.set(Dept::getIsPlatformCompany, dept.getIsPlatformCompany())
|
||||
.set(Dept::getIsBusinessDept, dept.getIsBusinessDept())
|
||||
.eq(Dept::getId, dept.getId()));
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将是否类标志规范为 0/1;空值按 0 处理。
|
||||
*/
|
||||
private Integer normalizeYesNoFlag(Integer flag) {
|
||||
return Integer.valueOf(1).equals(flag) ? 1 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -881,9 +901,9 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDeptCode(Dept dept, Dept parent) {
|
||||
private void validateDeptCode(Dept dept) {
|
||||
String deptCode = dept.getDeptCode();
|
||||
// 组织编码非必填,为空时存 null,避免唯一索引冲突
|
||||
// 组织编码非必填,为空时存 null,避免唯一索引冲突;不再校验 GWWL/上级编码+三位数字格式
|
||||
if (StringUtil.isBlank(deptCode)) {
|
||||
dept.setDeptCode(null);
|
||||
return;
|
||||
@@ -892,26 +912,6 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
||||
if (deptCode.length() > 30) {
|
||||
throw new ServiceException("组织编码不能超过30个字符");
|
||||
}
|
||||
// 顶级组织不依赖上级编码
|
||||
if (parent == null) {
|
||||
this.ensureDeptCodeUnique(dept, deptCode);
|
||||
dept.setDeptCode(deptCode);
|
||||
return;
|
||||
}
|
||||
if (StringUtil.isBlank(parent.getDeptCode())) {
|
||||
throw new ServiceException("请选择已配置组织编码的上级组织");
|
||||
}
|
||||
// 公司:GWWL+三位数字;部门:所属公司编码+三位数字;其他:上级编码+三位数字
|
||||
String expectedParentCode = parent.getDeptCode();
|
||||
if (DeptCategory.COMPANY.getCode().equals(dept.getDeptCategory())) {
|
||||
expectedParentCode = OAConvertConstant.OA_SYNC_ROOT_DEPT_CODE;
|
||||
} else if (DeptCategory.DEPT.getCode().equals(dept.getDeptCategory())
|
||||
&& StringUtil.isNotBlank(dept.getBelongCompanyCode())) {
|
||||
expectedParentCode = dept.getBelongCompanyCode();
|
||||
}
|
||||
if (!org.springblade.system.util.DeptCodeUtil.matchesChildCode(expectedParentCode, deptCode)) {
|
||||
throw new ServiceException("组织编码格式应为:" + expectedParentCode + "三位数字(不足补零,中间不加-)");
|
||||
}
|
||||
this.ensureDeptCodeUnique(dept, deptCode);
|
||||
dept.setDeptCode(deptCode);
|
||||
}
|
||||
|
||||
+32
-8
@@ -184,20 +184,44 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl<RoleMenuDataSc
|
||||
if (Func.isEmpty(roleIds) || Func.isBlank(menuCode)) {
|
||||
return RoleDataScopeVO.all();
|
||||
}
|
||||
Menu menu = menuMapper.selectOne(Wrappers.<Menu>lambdaQuery()
|
||||
.eq(Menu::getCode, menuCode)
|
||||
.eq(Menu::getIsDeleted, 0)
|
||||
.last("limit 1"));
|
||||
Menu menu = findMenuByCode(menuCode);
|
||||
if (Func.isEmpty(menu)) {
|
||||
return RoleDataScopeVO.all();
|
||||
}
|
||||
List<RoleMenuDataScope> scopeList = list(Wrappers.<RoleMenuDataScope>lambdaQuery()
|
||||
.in(RoleMenuDataScope::getRoleId, roleIds)
|
||||
.eq(RoleMenuDataScope::getMenuId, menu.getId())
|
||||
.eq(RoleMenuDataScope::getIsDeleted, 0));
|
||||
List<RoleMenuDataScope> scopeList = listScopes(roleIds, menu.getId());
|
||||
return mergeScopes(scopeList, userDeptIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleDataScopeVO resolveByMenuCodeOrEmpty(List<Long> roleIds, String menuCode, List<Long> userDeptIds) {
|
||||
if (Func.isEmpty(roleIds) || Func.isBlank(menuCode)) {
|
||||
return RoleDataScopeVO.none();
|
||||
}
|
||||
Menu menu = findMenuByCode(menuCode);
|
||||
if (Func.isEmpty(menu)) {
|
||||
return RoleDataScopeVO.none();
|
||||
}
|
||||
List<RoleMenuDataScope> scopeList = listScopes(roleIds, menu.getId());
|
||||
if (Func.isEmpty(scopeList)) {
|
||||
return RoleDataScopeVO.none();
|
||||
}
|
||||
return mergeScopes(scopeList, userDeptIds);
|
||||
}
|
||||
|
||||
private Menu findMenuByCode(String menuCode) {
|
||||
return menuMapper.selectOne(Wrappers.<Menu>lambdaQuery()
|
||||
.eq(Menu::getCode, menuCode)
|
||||
.eq(Menu::getIsDeleted, 0)
|
||||
.last("limit 1"));
|
||||
}
|
||||
|
||||
private List<RoleMenuDataScope> listScopes(List<Long> roleIds, Long menuId) {
|
||||
return list(Wrappers.<RoleMenuDataScope>lambdaQuery()
|
||||
.in(RoleMenuDataScope::getRoleId, roleIds)
|
||||
.eq(RoleMenuDataScope::getMenuId, menuId)
|
||||
.eq(RoleMenuDataScope::getIsDeleted, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleDataScopeVO resolveWidest(List<Long> roleIds, List<Long> userDeptIds) {
|
||||
if (Func.isEmpty(roleIds)) {
|
||||
|
||||
Reference in New Issue
Block a user