⚡ 优化角色数据权限、用户组织范围与流程完结处理人展示
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+5
-4
@@ -415,7 +415,8 @@ public class BusinessProcessServiceImpl extends ServiceImpl<BusinessProcessMappe
|
|||||||
businessProcess.setCompleteTime(new Date());
|
businessProcess.setCompleteTime(new Date());
|
||||||
businessProcess.setCurrentNodeIds(null);
|
businessProcess.setCurrentNodeIds(null);
|
||||||
businessProcess.setCurrentNodeNames(null);
|
businessProcess.setCurrentNodeNames(null);
|
||||||
businessProcess.setCurrentHandlers(null);
|
// 流程完结后当前处理人统一展示「流程结束」,不再保留最后处理人
|
||||||
|
businessProcess.setCurrentHandlers("流程结束");
|
||||||
boolean updated = this.updateById(businessProcess);
|
boolean updated = this.updateById(businessProcess);
|
||||||
log.info("标记流程完结 processInstanceId={} approved={} approveStatus={} result={}",
|
log.info("标记流程完结 processInstanceId={} approved={} approveStatus={} result={}",
|
||||||
processInstanceId, approved, approveStatus, updated);
|
processInstanceId, approved, approveStatus, updated);
|
||||||
@@ -1079,13 +1080,13 @@ public class BusinessProcessServiceImpl extends ServiceImpl<BusinessProcessMappe
|
|||||||
if (CollectionUtil.isEmpty(currentNodes)) {
|
if (CollectionUtil.isEmpty(currentNodes)) {
|
||||||
log.info("修改业务流程 当前节点处理人为空");
|
log.info("修改业务流程 当前节点处理人为空");
|
||||||
if (businessProcessId != null) {
|
if (businessProcessId != null) {
|
||||||
// 清空当前节点,当前处理人,接收时间
|
// 清空当前节点;完结时当前处理人改为「流程结束」,未完结则清空
|
||||||
log.info("修改业务流程 流程结束清空当前节点,当前处理人,接收时间 业务流程id:{} 流程实例id:{}", businessProcessId, processInstanceId);
|
log.info("修改业务流程 流程结束清空当前节点,更新当前处理人 业务流程id:{} 流程实例id:{} complete={}", businessProcessId, processInstanceId, complete);
|
||||||
this.lambdaUpdate()
|
this.lambdaUpdate()
|
||||||
.eq(BusinessProcess::getId, businessProcessId)
|
.eq(BusinessProcess::getId, businessProcessId)
|
||||||
.set(BusinessProcess::getCurrentNodeIds, null)
|
.set(BusinessProcess::getCurrentNodeIds, null)
|
||||||
.set(BusinessProcess::getCurrentNodeNames, null)
|
.set(BusinessProcess::getCurrentNodeNames, null)
|
||||||
.set(BusinessProcess::getCurrentHandlers, null)
|
.set(BusinessProcess::getCurrentHandlers, complete ? "流程结束" : null)
|
||||||
.set(complete, BusinessProcess::getIsCompleted, true)
|
.set(complete, BusinessProcess::getIsCompleted, true)
|
||||||
.set(complete, BusinessProcess::getCompleteTime, new Date())
|
.set(complete, BusinessProcess::getCompleteTime, new Date())
|
||||||
.set(BusinessProcess::getUpdateTime, new Date())
|
.set(BusinessProcess::getUpdateTime, new Date())
|
||||||
|
|||||||
+2
-1
@@ -31,6 +31,7 @@ import cn.idev.excel.annotation.write.style.ColumnWidth;
|
|||||||
import cn.idev.excel.annotation.write.style.ContentRowHeight;
|
import cn.idev.excel.annotation.write.style.ContentRowHeight;
|
||||||
import cn.idev.excel.annotation.write.style.HeadRowHeight;
|
import cn.idev.excel.annotation.write.style.HeadRowHeight;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.springblade.system.pojo.context.IPhone;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -44,7 +45,7 @@ import java.io.Serializable;
|
|||||||
@ColumnWidth(25)
|
@ColumnWidth(25)
|
||||||
@HeadRowHeight(20)
|
@HeadRowHeight(20)
|
||||||
@ContentRowHeight(18)
|
@ContentRowHeight(18)
|
||||||
public class UserExcel implements Serializable {
|
public class UserExcel implements Serializable, IPhone {
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
+65
-14
@@ -222,42 +222,93 @@
|
|||||||
) menu ORDER BY sort
|
) menu ORDER BY sort
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 授权树与侧边栏一致:仅返回系统可见菜单(is_display=1),并保留其下按钮权限节点 -->
|
||||||
<select id="grantTree" resultMap="treeNodeResultMap">
|
<select id="grantTree" resultMap="treeNodeResultMap">
|
||||||
select id, parent_id, name as title, id as "value", id as "key" from blade_menu where is_deleted = 0 order by sort
|
select id, parent_id, name as title, id as "value", id as "key"
|
||||||
|
from blade_menu
|
||||||
|
where is_deleted = 0
|
||||||
|
and (
|
||||||
|
(category = 1 and ifnull(is_display, 1) = 1)
|
||||||
|
or (
|
||||||
|
category <> 1
|
||||||
|
and ifnull(is_display, 1) = 1
|
||||||
|
and parent_id in (
|
||||||
|
select id from blade_menu
|
||||||
|
where is_deleted = 0 and category = 1 and ifnull(is_display, 1) = 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
order by sort
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="grantTreeByRole" resultMap="treeNodeResultMap">
|
<select id="grantTreeByRole" resultMap="treeNodeResultMap">
|
||||||
select id, parent_id, name as title, id as "value", id as "key" from blade_menu where is_deleted = 0
|
select id, parent_id, name as title, id as "value", id as "key"
|
||||||
and id in ( select menu_id from blade_role_menu where role_id in
|
from blade_menu
|
||||||
|
where is_deleted = 0
|
||||||
|
and (
|
||||||
|
(category = 1 and ifnull(is_display, 1) = 1)
|
||||||
|
or (
|
||||||
|
category <> 1
|
||||||
|
and ifnull(is_display, 1) = 1
|
||||||
|
and parent_id in (
|
||||||
|
select id from blade_menu
|
||||||
|
where is_deleted = 0 and category = 1 and ifnull(is_display, 1) = 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
and (
|
||||||
|
id in (
|
||||||
|
select menu_id from blade_role_menu where role_id in
|
||||||
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
|
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
|
||||||
#{item}
|
#{item}
|
||||||
</foreach> )
|
</foreach>
|
||||||
|
)
|
||||||
or id in (
|
or id in (
|
||||||
select parent_id from blade_menu where is_deleted = 0
|
select parent_id from blade_menu
|
||||||
and id in ( select menu_id from blade_role_menu where role_id in
|
where is_deleted = 0
|
||||||
|
and ifnull(is_display, 1) = 1
|
||||||
|
and id in (
|
||||||
|
select menu_id from blade_role_menu where role_id in
|
||||||
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
|
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
|
||||||
#{item}
|
#{item}
|
||||||
</foreach> )
|
</foreach>
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
order by sort
|
order by sort
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="grantTopTree" resultMap="treeNodeResultMap">
|
<select id="grantTopTree" resultMap="treeNodeResultMap">
|
||||||
select id, parent_id, name as title, id as "value", id as "key" from blade_menu where category = 1 and is_deleted = 0 order by sort
|
select id, parent_id, name as title, id as "value", id as "key"
|
||||||
|
from blade_menu
|
||||||
|
where category = 1 and is_deleted = 0 and ifnull(is_display, 1) = 1
|
||||||
|
order by sort
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="grantTopTreeByRole" resultMap="treeNodeResultMap">
|
<select id="grantTopTreeByRole" resultMap="treeNodeResultMap">
|
||||||
select id, parent_id, name as title, id as "value", id as "key" from blade_menu where category = 1 and is_deleted = 0
|
select id, parent_id, name as title, id as "value", id as "key"
|
||||||
and id in ( select menu_id from blade_role_menu where role_id in
|
from blade_menu
|
||||||
|
where category = 1
|
||||||
|
and is_deleted = 0
|
||||||
|
and ifnull(is_display, 1) = 1
|
||||||
|
and (
|
||||||
|
id in (
|
||||||
|
select menu_id from blade_role_menu where role_id in
|
||||||
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
|
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
|
||||||
#{item}
|
#{item}
|
||||||
</foreach> )
|
</foreach>
|
||||||
|
)
|
||||||
or id in (
|
or id in (
|
||||||
select parent_id from blade_menu where is_deleted = 0
|
select parent_id from blade_menu
|
||||||
and id in ( select menu_id from blade_role_menu where role_id in
|
where is_deleted = 0
|
||||||
|
and ifnull(is_display, 1) = 1
|
||||||
|
and id in (
|
||||||
|
select menu_id from blade_role_menu where role_id in
|
||||||
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
|
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
|
||||||
#{item}
|
#{item}
|
||||||
</foreach> )
|
</foreach>
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
order by sort
|
order by sort
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
+5
-3
@@ -41,7 +41,8 @@ import java.util.List;
|
|||||||
public interface IRoleMenuDataScopeService extends BaseService<RoleMenuDataScope> {
|
public interface IRoleMenuDataScopeService extends BaseService<RoleMenuDataScope> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询角色数据权限配置树
|
* 查询角色数据权限配置树。
|
||||||
|
* 菜单范围与该角色已保存的菜单权限一致,已配置的数据权限不会被清除。
|
||||||
*
|
*
|
||||||
* @param roleId 角色主键
|
* @param roleId 角色主键
|
||||||
* @return 菜单树与已配置权限
|
* @return 菜单树与已配置权限
|
||||||
@@ -57,11 +58,12 @@ public interface IRoleMenuDataScopeService extends BaseService<RoleMenuDataScope
|
|||||||
boolean submit(RoleMenuDataScopeDTO dto);
|
boolean submit(RoleMenuDataScopeDTO dto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按菜单编码合并解析角色数据权限
|
* 按菜单编码合并解析角色数据权限。
|
||||||
|
* 全部组织、本人创建直接按角色权限返回;所在部门及下级的组织范围由调用方按用户数据权限组织补齐。
|
||||||
*
|
*
|
||||||
* @param roleIds 角色ID集合
|
* @param roleIds 角色ID集合
|
||||||
* @param menuCode 菜单编码
|
* @param menuCode 菜单编码
|
||||||
* @param userDeptIds 用户所属组织
|
* @param userDeptIds 用户所属组织(所在部门及下级不再据此展开)
|
||||||
* @return 解析结果
|
* @return 解析结果
|
||||||
*/
|
*/
|
||||||
RoleDataScopeVO resolveByMenuCode(List<Long> roleIds, String menuCode, List<Long> userDeptIds);
|
RoleDataScopeVO resolveByMenuCode(List<Long> roleIds, String menuCode, List<Long> userDeptIds);
|
||||||
|
|||||||
+9
@@ -401,4 +401,13 @@ public interface IUserService extends BaseService<User> {
|
|||||||
* @param user 用户对象
|
* @param user 用户对象
|
||||||
*/
|
*/
|
||||||
void encryptPhone(IPhone user);
|
void encryptPhone(IPhone user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首次同步时初始化数据管理组织;已有配置则跳过更新。
|
||||||
|
*
|
||||||
|
* @param userId 用户主键
|
||||||
|
* @param deptIds 所属组织 ID 集合
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
boolean initManageDeptScopeIfAbsent(Long userId, List<Long> deptIds);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -49,6 +49,7 @@ import org.springblade.system.mapper.DeptMapper;
|
|||||||
import org.springblade.system.pojo.entity.Dept;
|
import org.springblade.system.pojo.entity.Dept;
|
||||||
import org.springblade.system.pojo.entity.User;
|
import org.springblade.system.pojo.entity.User;
|
||||||
import org.springblade.system.pojo.enums.DeptCategory;
|
import org.springblade.system.pojo.enums.DeptCategory;
|
||||||
|
import org.springblade.system.pojo.enums.RoleDataScopeType;
|
||||||
import org.springblade.system.pojo.vo.DeptVO;
|
import org.springblade.system.pojo.vo.DeptVO;
|
||||||
import org.springblade.system.pojo.vo.RoleDataScopeVO;
|
import org.springblade.system.pojo.vo.RoleDataScopeVO;
|
||||||
import org.springblade.system.pojo.vo.UserVO;
|
import org.springblade.system.pojo.vo.UserVO;
|
||||||
@@ -271,6 +272,15 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
|||||||
allowedDeptIds.add(deptId);
|
allowedDeptIds.add(deptId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (RoleDataScopeType.DEPT_AND_CHILD.matches(scope.getScopeType())) {
|
||||||
|
// 所在部门及下级按用户数据权限组织,不按所属组织展开
|
||||||
|
if (Func.isNotEmpty(scope.getDeptIds())) {
|
||||||
|
allowedDeptIds.addAll(scope.getDeptIds());
|
||||||
|
}
|
||||||
|
List<Long> manageDeptIds = userService.resolveManageDeptIds(userId);
|
||||||
|
if (Func.isNotEmpty(manageDeptIds)) {
|
||||||
|
allowedDeptIds.addAll(manageDeptIds);
|
||||||
|
}
|
||||||
} else if (Func.isNotEmpty(scope.getDeptIds())) {
|
} else if (Func.isNotEmpty(scope.getDeptIds())) {
|
||||||
allowedDeptIds.addAll(scope.getDeptIds());
|
allowedDeptIds.addAll(scope.getDeptIds());
|
||||||
}
|
}
|
||||||
|
|||||||
+16
@@ -34,6 +34,7 @@ import org.springblade.common.constant.CommonConstant;
|
|||||||
import org.springblade.core.secure.utils.AuthUtil;
|
import org.springblade.core.secure.utils.AuthUtil;
|
||||||
import org.springblade.core.tool.constant.BladeConstant;
|
import org.springblade.core.tool.constant.BladeConstant;
|
||||||
import org.springblade.core.tool.utils.DigestUtil;
|
import org.springblade.core.tool.utils.DigestUtil;
|
||||||
|
import org.springblade.core.tool.utils.Func;
|
||||||
import org.springblade.system.cache.ParamCache;
|
import org.springblade.system.cache.ParamCache;
|
||||||
import org.springblade.system.convert.UserConvert;
|
import org.springblade.system.convert.UserConvert;
|
||||||
import org.springblade.system.log.ComposeLogUtil;
|
import org.springblade.system.log.ComposeLogUtil;
|
||||||
@@ -790,6 +791,21 @@ public class OaUserListSyncHelper {
|
|||||||
if (CollectionUtil.isNotEmpty(updateUserParams)) {
|
if (CollectionUtil.isNotEmpty(updateUserParams)) {
|
||||||
userService.updateBatchById(updateUserParams);
|
userService.updateBatchById(updateUserParams);
|
||||||
}
|
}
|
||||||
|
// 首次同步:数据管理组织=所属组织;已有数据管理组织的用户下次同步跳过
|
||||||
|
Set<Long> newUserIds = addUsers.stream()
|
||||||
|
.map(User::getId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
for (UserDeptIdsVO userDeptIds : list) {
|
||||||
|
if (userDeptIds.getUserId() == null || !newUserIds.contains(userDeptIds.getUserId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<Long> deptIdList = Func.toLongList(userDeptIds.getDeptIds());
|
||||||
|
if (Func.isEmpty(deptIdList)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
userService.initManageDeptScopeIfAbsent(userDeptIds.getUserId(), deptIdList);
|
||||||
|
}
|
||||||
return new PersonSyncCount(syncedCount, skippedCount, removedCount);
|
return new PersonSyncCount(syncedCount, skippedCount, removedCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+64
-38
@@ -34,13 +34,14 @@ import org.springblade.core.secure.utils.AuthUtil;
|
|||||||
import org.springblade.core.tool.node.ForestNodeMerger;
|
import org.springblade.core.tool.node.ForestNodeMerger;
|
||||||
import org.springblade.core.tool.node.TreeNode;
|
import org.springblade.core.tool.node.TreeNode;
|
||||||
import org.springblade.core.tool.utils.Func;
|
import org.springblade.core.tool.utils.Func;
|
||||||
import org.springblade.system.cache.SysCache;
|
|
||||||
import org.springblade.system.mapper.MenuMapper;
|
import org.springblade.system.mapper.MenuMapper;
|
||||||
import org.springblade.system.mapper.RoleMenuDataScopeDeptMapper;
|
import org.springblade.system.mapper.RoleMenuDataScopeDeptMapper;
|
||||||
import org.springblade.system.mapper.RoleMenuDataScopeMapper;
|
import org.springblade.system.mapper.RoleMenuDataScopeMapper;
|
||||||
|
import org.springblade.system.mapper.RoleMenuMapper;
|
||||||
import org.springblade.system.pojo.dto.RoleMenuDataScopeDTO;
|
import org.springblade.system.pojo.dto.RoleMenuDataScopeDTO;
|
||||||
import org.springblade.system.pojo.entity.Menu;
|
import org.springblade.system.pojo.entity.Menu;
|
||||||
import org.springblade.system.pojo.entity.Role;
|
import org.springblade.system.pojo.entity.Role;
|
||||||
|
import org.springblade.system.pojo.entity.RoleMenu;
|
||||||
import org.springblade.system.pojo.entity.RoleMenuDataScope;
|
import org.springblade.system.pojo.entity.RoleMenuDataScope;
|
||||||
import org.springblade.system.pojo.entity.RoleMenuDataScopeDept;
|
import org.springblade.system.pojo.entity.RoleMenuDataScopeDept;
|
||||||
import org.springblade.system.pojo.enums.RoleDataScopeType;
|
import org.springblade.system.pojo.enums.RoleDataScopeType;
|
||||||
@@ -58,6 +59,7 @@ import java.util.LinkedHashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
|
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
|
||||||
@@ -74,6 +76,7 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl<RoleMenuDataSc
|
|||||||
|
|
||||||
private final RoleMenuDataScopeDeptMapper roleMenuDataScopeDeptMapper;
|
private final RoleMenuDataScopeDeptMapper roleMenuDataScopeDeptMapper;
|
||||||
private final MenuMapper menuMapper;
|
private final MenuMapper menuMapper;
|
||||||
|
private final RoleMenuMapper roleMenuMapper;
|
||||||
private final IRoleService roleService;
|
private final IRoleService roleService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -87,7 +90,8 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl<RoleMenuDataSc
|
|||||||
}
|
}
|
||||||
RoleMenuDataScopeTreeVO treeVO = new RoleMenuDataScopeTreeVO();
|
RoleMenuDataScopeTreeVO treeVO = new RoleMenuDataScopeTreeVO();
|
||||||
treeVO.setRoleName(role.getRoleName());
|
treeVO.setRoleName(role.getRoleName());
|
||||||
List<TreeNode> menuNodes = menuMapper.grantTree();
|
// 数据权限菜单与已保存的菜单权限保持一致;这里只收窄展示范围,不删除已有数据权限配置
|
||||||
|
List<TreeNode> menuNodes = filterGrantedMenus(menuMapper.grantTree(), roleId);
|
||||||
treeVO.setMenuTree(ForestNodeMerger.merge(menuNodes));
|
treeVO.setMenuTree(ForestNodeMerger.merge(menuNodes));
|
||||||
|
|
||||||
List<RoleMenuDataScope> scopeList = list(Wrappers.<RoleMenuDataScope>lambdaQuery()
|
List<RoleMenuDataScope> scopeList = list(Wrappers.<RoleMenuDataScope>lambdaQuery()
|
||||||
@@ -189,7 +193,7 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl<RoleMenuDataSc
|
|||||||
return RoleDataScopeVO.all();
|
return RoleDataScopeVO.all();
|
||||||
}
|
}
|
||||||
List<RoleMenuDataScope> scopeList = listScopes(roleIds, menu.getId());
|
List<RoleMenuDataScope> scopeList = listScopes(roleIds, menu.getId());
|
||||||
return mergeScopes(scopeList, userDeptIds);
|
return mergeScopes(scopeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -205,7 +209,45 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl<RoleMenuDataSc
|
|||||||
if (Func.isEmpty(scopeList)) {
|
if (Func.isEmpty(scopeList)) {
|
||||||
return RoleDataScopeVO.none();
|
return RoleDataScopeVO.none();
|
||||||
}
|
}
|
||||||
return mergeScopes(scopeList, userDeptIds);
|
return mergeScopes(scopeList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按角色已分配菜单过滤数据权限树,并补齐上级节点以保持层级。
|
||||||
|
* 未勾选的菜单不再展示;已配置的数据权限记录保持不变,菜单重新勾选后配置仍在。
|
||||||
|
*
|
||||||
|
* @param menuNodes 全部菜单节点
|
||||||
|
* @param roleId 角色主键
|
||||||
|
* @return 与菜单权限一致的节点
|
||||||
|
*/
|
||||||
|
private List<TreeNode> filterGrantedMenus(List<TreeNode> menuNodes, Long roleId) {
|
||||||
|
if (Func.isEmpty(menuNodes)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
Set<Long> grantedMenuIds = roleMenuMapper.selectList(Wrappers.<RoleMenu>lambdaQuery()
|
||||||
|
.eq(RoleMenu::getRoleId, roleId))
|
||||||
|
.stream()
|
||||||
|
.map(RoleMenu::getMenuId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
if (grantedMenuIds.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
Map<Long, Long> parentMap = menuNodes.stream()
|
||||||
|
.filter(node -> node.getId() != null)
|
||||||
|
.collect(Collectors.toMap(TreeNode::getId, TreeNode::getParentId, (left, right) -> left));
|
||||||
|
Set<Long> visibleMenuIds = new LinkedHashSet<>(grantedMenuIds);
|
||||||
|
for (Long menuId : grantedMenuIds) {
|
||||||
|
Long parentId = parentMap.get(menuId);
|
||||||
|
int guard = 0;
|
||||||
|
while (parentId != null && parentId > 0 && guard++ < 32) {
|
||||||
|
visibleMenuIds.add(parentId);
|
||||||
|
parentId = parentMap.get(parentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return menuNodes.stream()
|
||||||
|
.filter(node -> node.getId() != null && visibleMenuIds.contains(node.getId()))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Menu findMenuByCode(String menuCode) {
|
private Menu findMenuByCode(String menuCode) {
|
||||||
@@ -230,30 +272,33 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl<RoleMenuDataSc
|
|||||||
List<RoleMenuDataScope> scopeList = list(Wrappers.<RoleMenuDataScope>lambdaQuery()
|
List<RoleMenuDataScope> scopeList = list(Wrappers.<RoleMenuDataScope>lambdaQuery()
|
||||||
.in(RoleMenuDataScope::getRoleId, roleIds)
|
.in(RoleMenuDataScope::getRoleId, roleIds)
|
||||||
.eq(RoleMenuDataScope::getIsDeleted, 0));
|
.eq(RoleMenuDataScope::getIsDeleted, 0));
|
||||||
return mergeScopes(scopeList, userDeptIds);
|
return mergeScopes(scopeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RoleDataScopeVO mergeScopes(List<RoleMenuDataScope> scopeList, List<Long> userDeptIds) {
|
/**
|
||||||
|
* 合并多条角色菜单数据权限。
|
||||||
|
* 全部组织、本人创建优先于组织范围;所在部门及下级不在此处展开所属组织,
|
||||||
|
* 由调用方替换为用户的数据权限组织。
|
||||||
|
*/
|
||||||
|
private RoleDataScopeVO mergeScopes(List<RoleMenuDataScope> scopeList) {
|
||||||
if (Func.isEmpty(scopeList)) {
|
if (Func.isEmpty(scopeList)) {
|
||||||
return RoleDataScopeVO.all();
|
return RoleDataScopeVO.all();
|
||||||
}
|
}
|
||||||
boolean hasAll = false;
|
boolean hasAll = false;
|
||||||
boolean hasDeptScope = false;
|
boolean hasDeptAndChild = false;
|
||||||
|
boolean hasCustom = false;
|
||||||
boolean hasOwn = false;
|
boolean hasOwn = false;
|
||||||
LinkedHashSet<Long> allowedDeptIds = new LinkedHashSet<>();
|
LinkedHashSet<Long> customDeptIds = new LinkedHashSet<>();
|
||||||
Map<Long, List<Long>> customDeptMap = loadCustomDeptMap(scopeList);
|
Map<Long, List<Long>> customDeptMap = loadCustomDeptMap(scopeList);
|
||||||
|
|
||||||
for (RoleMenuDataScope scope : scopeList) {
|
for (RoleMenuDataScope scope : scopeList) {
|
||||||
RoleDataScopeType type = RoleDataScopeType.of(scope.getScopeType());
|
RoleDataScopeType type = RoleDataScopeType.of(scope.getScopeType());
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ALL -> hasAll = true;
|
case ALL -> hasAll = true;
|
||||||
case DEPT_AND_CHILD -> {
|
case DEPT_AND_CHILD -> hasDeptAndChild = true;
|
||||||
hasDeptScope = true;
|
|
||||||
allowedDeptIds.addAll(expandDeptIds(userDeptIds, true));
|
|
||||||
}
|
|
||||||
case CUSTOM -> {
|
case CUSTOM -> {
|
||||||
hasDeptScope = true;
|
hasCustom = true;
|
||||||
allowedDeptIds.addAll(customDeptMap.getOrDefault(scope.getId(), Collections.emptyList()));
|
customDeptIds.addAll(customDeptMap.getOrDefault(scope.getId(), Collections.emptyList()));
|
||||||
}
|
}
|
||||||
case OWN_CREATE -> hasOwn = true;
|
case OWN_CREATE -> hasOwn = true;
|
||||||
default -> {
|
default -> {
|
||||||
@@ -263,8 +308,11 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl<RoleMenuDataSc
|
|||||||
if (hasAll) {
|
if (hasAll) {
|
||||||
return RoleDataScopeVO.all();
|
return RoleDataScopeVO.all();
|
||||||
}
|
}
|
||||||
if (hasDeptScope) {
|
if (hasDeptAndChild) {
|
||||||
return RoleDataScopeVO.ofDepts(RoleDataScopeType.CUSTOM.getCode(), new ArrayList<>(allowedDeptIds));
|
return RoleDataScopeVO.ofDepts(RoleDataScopeType.DEPT_AND_CHILD.getCode(), new ArrayList<>(customDeptIds));
|
||||||
|
}
|
||||||
|
if (hasCustom) {
|
||||||
|
return RoleDataScopeVO.ofDepts(RoleDataScopeType.CUSTOM.getCode(), new ArrayList<>(customDeptIds));
|
||||||
}
|
}
|
||||||
if (hasOwn) {
|
if (hasOwn) {
|
||||||
return RoleDataScopeVO.ownCreate();
|
return RoleDataScopeVO.ownCreate();
|
||||||
@@ -287,26 +335,4 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl<RoleMenuDataSc
|
|||||||
Collectors.mapping(RoleMenuDataScopeDept::getDeptId, Collectors.toList())));
|
Collectors.mapping(RoleMenuDataScopeDept::getDeptId, Collectors.toList())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Long> expandDeptIds(List<Long> baseDeptIds, boolean includeChildren) {
|
|
||||||
if (Func.isEmpty(baseDeptIds)) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
LinkedHashSet<Long> result = new LinkedHashSet<>();
|
|
||||||
for (Long deptId : baseDeptIds) {
|
|
||||||
if (Func.isEmpty(deptId) || deptId <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (includeChildren) {
|
|
||||||
List<Long> childIds = SysCache.getDeptChildIds(deptId);
|
|
||||||
if (Func.isNotEmpty(childIds)) {
|
|
||||||
result.addAll(childIds);
|
|
||||||
} else {
|
|
||||||
result.add(deptId);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result.add(deptId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new ArrayList<>(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+44
-2
@@ -256,6 +256,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
user.setStatus(status);
|
user.setStatus(status);
|
||||||
user.setIsOa(1);
|
user.setIsOa(1);
|
||||||
user.setSyncTime(new Date());
|
user.setSyncTime(new Date());
|
||||||
|
// 首次同步:数据管理组织默认等于所属组织
|
||||||
|
user.setDataScopeDeptIds(Func.toLongList(user.getDeptId()));
|
||||||
applyUserDefaults(user);
|
applyUserDefaults(user);
|
||||||
return saveUser(user);
|
return saveUser(user);
|
||||||
}
|
}
|
||||||
@@ -326,6 +328,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
if (userCount > 0L) {
|
if (userCount > 0L) {
|
||||||
throw new ServiceException(StringUtil.format("当前用户 [{}] 已存在!", user.getAccount()));
|
throw new ServiceException(StringUtil.format("当前用户 [{}] 已存在!", user.getAccount()));
|
||||||
}
|
}
|
||||||
|
encryptPhone(user);
|
||||||
Long phoneCount = baseMapper.selectCount(
|
Long phoneCount = baseMapper.selectCount(
|
||||||
Wrappers.<User>query().lambda()
|
Wrappers.<User>query().lambda()
|
||||||
.eq(User::getTenantId, tenantId)
|
.eq(User::getTenantId, tenantId)
|
||||||
@@ -373,6 +376,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean submitUserInfo(User user) {
|
private boolean submitUserInfo(User user) {
|
||||||
|
encryptPhone(user);
|
||||||
Long phoneCount = baseMapper.selectCount(
|
Long phoneCount = baseMapper.selectCount(
|
||||||
Wrappers.<User>query().lambda()
|
Wrappers.<User>query().lambda()
|
||||||
.eq(User::getTenantId, AuthUtil.getTenantId())
|
.eq(User::getTenantId, AuthUtil.getTenantId())
|
||||||
@@ -736,6 +740,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
public List<UserExcel> exportUser(Wrapper<User> queryWrapper) {
|
public List<UserExcel> exportUser(Wrapper<User> queryWrapper) {
|
||||||
List<UserExcel> userList = baseMapper.exportUser(queryWrapper);
|
List<UserExcel> userList = baseMapper.exportUser(queryWrapper);
|
||||||
userList.forEach(user -> {
|
userList.forEach(user -> {
|
||||||
|
decryptPhone(user);
|
||||||
user.setUserTypeName(DictCache.getValue(DictEnum.USER_TYPE, user.getUserType()));
|
user.setUserTypeName(DictCache.getValue(DictEnum.USER_TYPE, user.getUserType()));
|
||||||
user.setRoleName(StringUtil.join(SysCache.getRoleNames(user.getRoleId())));
|
user.setRoleName(StringUtil.join(SysCache.getRoleNames(user.getRoleId())));
|
||||||
user.setDeptName(StringUtil.join(SysCache.getDeptNames(user.getDeptId())));
|
user.setDeptName(StringUtil.join(SysCache.getDeptNames(user.getDeptId())));
|
||||||
@@ -1105,6 +1110,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
}
|
}
|
||||||
validatePlainPassword(user.getPassword());
|
validatePlainPassword(user.getPassword());
|
||||||
user.setPassword(DigestUtil.encrypt(user.getPassword()));
|
user.setPassword(DigestUtil.encrypt(user.getPassword()));
|
||||||
|
encryptPhone(user);
|
||||||
Long userCount = baseMapper.selectCount(Wrappers.<User>query().lambda().eq(User::getTenantId, tenantId).eq(User::getAccount, user.getAccount()));
|
Long userCount = baseMapper.selectCount(Wrappers.<User>query().lambda().eq(User::getTenantId, tenantId).eq(User::getAccount, user.getAccount()));
|
||||||
if (userCount > 0L && Func.isEmpty(user.getId())) {
|
if (userCount > 0L && Func.isEmpty(user.getId())) {
|
||||||
throw new ServiceException(StringUtil.format("当前用户 [{}] 已存在!", user.getAccount()));
|
throw new ServiceException(StringUtil.format("当前用户 [{}] 已存在!", user.getAccount()));
|
||||||
@@ -1301,9 +1307,45 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
if (user == null) {
|
if (user == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (StringUtil.isNotBlank(user.getPhone())) {
|
String phone = user.getPhone();
|
||||||
user.setPhone(Hex.toHexString(SM2Util.encrypt(user.getPhone(), properties.getPublicKey())));
|
if (StringUtil.isBlank(phone)) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// 已是 SM2 密文则跳过,避免重复加密
|
||||||
|
if (phone.length() > 20 && isSm2HexCipher(phone)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
user.setPhone(Hex.toHexString(SM2Util.encrypt(phone, properties.getPublicKey())));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首次同步初始化数据管理组织;已有配置时跳过,避免后续同步覆盖手工调整。
|
||||||
|
*
|
||||||
|
* @param userId 用户主键
|
||||||
|
* @param deptIds 所属组织 ID 集合
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean initManageDeptScopeIfAbsent(Long userId, List<Long> deptIds) {
|
||||||
|
if (Func.isEmpty(userId) || userId <= 0 || Func.isEmpty(deptIds)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Long existsCount = userDataScopeMapper.selectCount(Wrappers.<UserDataScope>lambdaQuery()
|
||||||
|
.eq(UserDataScope::getUserId, userId));
|
||||||
|
if (existsCount != null && existsCount > 0L) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
User user = new User();
|
||||||
|
user.setId(userId);
|
||||||
|
user.setDataScopeDeptIds(deptIds.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(deptId -> deptId > 0)
|
||||||
|
.distinct()
|
||||||
|
.toList());
|
||||||
|
if (Func.isEmpty(user.getDataScopeDeptIds())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return submitUserScopes(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validatePlainPassword(String password) {
|
private void validatePlainPassword(String password) {
|
||||||
|
|||||||
+4
@@ -28,6 +28,7 @@ package org.springblade.system.wrapper;
|
|||||||
import org.springblade.core.mp.support.BaseEntityWrapper;
|
import org.springblade.core.mp.support.BaseEntityWrapper;
|
||||||
import org.springblade.core.tool.utils.BeanUtil;
|
import org.springblade.core.tool.utils.BeanUtil;
|
||||||
import org.springblade.core.tool.utils.Func;
|
import org.springblade.core.tool.utils.Func;
|
||||||
|
import org.springblade.core.tool.utils.SpringUtil;
|
||||||
import org.springblade.core.tool.utils.StringPool;
|
import org.springblade.core.tool.utils.StringPool;
|
||||||
import org.springblade.core.tool.utils.StringUtil;
|
import org.springblade.core.tool.utils.StringUtil;
|
||||||
import org.springblade.system.cache.DictCache;
|
import org.springblade.system.cache.DictCache;
|
||||||
@@ -36,6 +37,7 @@ import org.springblade.system.pojo.entity.Tenant;
|
|||||||
import org.springblade.system.pojo.entity.User;
|
import org.springblade.system.pojo.entity.User;
|
||||||
import org.springblade.system.pojo.enums.DictEnum;
|
import org.springblade.system.pojo.enums.DictEnum;
|
||||||
import org.springblade.system.pojo.vo.UserVO;
|
import org.springblade.system.pojo.vo.UserVO;
|
||||||
|
import org.springblade.system.service.IUserService;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -57,6 +59,8 @@ public class UserWrapper extends BaseEntityWrapper<User, UserVO> {
|
|||||||
if (userVO == null) {
|
if (userVO == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
// 列表/详情展示解密后的明文手机号,避免 SM2 密文被当成手机号脱敏成乱码
|
||||||
|
SpringUtil.getBean(IUserService.class).decryptPhone(userVO);
|
||||||
Tenant tenant = SysCache.getTenant(user.getTenantId());
|
Tenant tenant = SysCache.getTenant(user.getTenantId());
|
||||||
if (tenant != null) {
|
if (tenant != null) {
|
||||||
userVO.setTenantName(tenant.getTenantName());
|
userVO.setTenantName(tenant.getTenantName());
|
||||||
|
|||||||
+20
-20
@@ -128,7 +128,7 @@ public final class MkProcessBizHandlers {
|
|||||||
entity.setApprovalStatus(change ? "change_approved" : "approved");
|
entity.setApprovalStatus(change ? "change_approved" : "approved");
|
||||||
entity.setEffectiveType("formal");
|
entity.setEffectiveType("formal");
|
||||||
entity.setCurrentNode("审核通过");
|
entity.setCurrentNode("审核通过");
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
entity.setApprovedTime(LocalDateTime.now());
|
entity.setApprovedTime(LocalDateTime.now());
|
||||||
// HCS 推送:审批通过置待同步状态,更新成功后即时推送,扫描任务保留兜底(ADR-0001 修订,前端接入设计 §6)
|
// HCS 推送:审批通过置待同步状态,更新成功后即时推送,扫描任务保留兜底(ADR-0001 修订,前端接入设计 §6)
|
||||||
entity.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
entity.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||||
@@ -149,7 +149,7 @@ public final class MkProcessBizHandlers {
|
|||||||
boolean change = "change_reviewing".equals(entity.getApprovalStatus());
|
boolean change = "change_reviewing".equals(entity.getApprovalStatus());
|
||||||
entity.setApprovalStatus(change ? "change_rejected" : "rejected");
|
entity.setApprovalStatus(change ? "change_rejected" : "rejected");
|
||||||
entity.setCurrentNode("审核不通过");
|
entity.setCurrentNode("审核不通过");
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
return service.updateById(entity);
|
return service.updateById(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,7 @@ public final class MkProcessBizHandlers {
|
|||||||
Long projectId = service.approve(id);
|
Long projectId = service.approve(id);
|
||||||
entity = service.getById(id);
|
entity = service.getById(id);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(entity);
|
service.updateById(entity);
|
||||||
}
|
}
|
||||||
if (projectId != null) {
|
if (projectId != null) {
|
||||||
@@ -219,7 +219,7 @@ public final class MkProcessBizHandlers {
|
|||||||
boolean rejected = service.reject(id);
|
boolean rejected = service.reject(id);
|
||||||
entity = service.getById(id);
|
entity = service.getById(id);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(entity);
|
service.updateById(entity);
|
||||||
}
|
}
|
||||||
return rejected;
|
return rejected;
|
||||||
@@ -273,7 +273,7 @@ public final class MkProcessBizHandlers {
|
|||||||
Long contractId = service.approve(id);
|
Long contractId = service.approve(id);
|
||||||
entity = service.getById(id);
|
entity = service.getById(id);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(entity);
|
service.updateById(entity);
|
||||||
}
|
}
|
||||||
if (contractId != null) {
|
if (contractId != null) {
|
||||||
@@ -291,7 +291,7 @@ public final class MkProcessBizHandlers {
|
|||||||
boolean rejected = service.reject(id);
|
boolean rejected = service.reject(id);
|
||||||
entity = service.getById(id);
|
entity = service.getById(id);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(entity);
|
service.updateById(entity);
|
||||||
}
|
}
|
||||||
return rejected;
|
return rejected;
|
||||||
@@ -348,7 +348,7 @@ public final class MkProcessBizHandlers {
|
|||||||
boolean change = "change_reviewing".equals(entity.getApprovalStatus());
|
boolean change = "change_reviewing".equals(entity.getApprovalStatus());
|
||||||
entity.setApprovalStatus(change ? "change_approved" : "approved");
|
entity.setApprovalStatus(change ? "change_approved" : "approved");
|
||||||
entity.setCurrentNode("审核通过");
|
entity.setCurrentNode("审核通过");
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
// HCS 推送:审批通过置待同步状态,更新成功后即时推送,扫描任务保留兜底(ADR-0001 修订,前端接入设计 §6)
|
// HCS 推送:审批通过置待同步状态,更新成功后即时推送,扫描任务保留兜底(ADR-0001 修订,前端接入设计 §6)
|
||||||
entity.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
entity.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||||
boolean updated = service.updateById(entity);
|
boolean updated = service.updateById(entity);
|
||||||
@@ -368,7 +368,7 @@ public final class MkProcessBizHandlers {
|
|||||||
boolean change = "change_reviewing".equals(entity.getApprovalStatus());
|
boolean change = "change_reviewing".equals(entity.getApprovalStatus());
|
||||||
entity.setApprovalStatus(change ? "change_rejected" : "rejected");
|
entity.setApprovalStatus(change ? "change_rejected" : "rejected");
|
||||||
entity.setCurrentNode("审核不通过");
|
entity.setCurrentNode("审核不通过");
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
return service.updateById(entity);
|
return service.updateById(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,7 +418,7 @@ public final class MkProcessBizHandlers {
|
|||||||
}
|
}
|
||||||
entity.setApprovalStatus("approved");
|
entity.setApprovalStatus("approved");
|
||||||
entity.setCurrentNode("审核通过");
|
entity.setCurrentNode("审核通过");
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
entity.setApprovedTime(LocalDateTime.now());
|
entity.setApprovedTime(LocalDateTime.now());
|
||||||
return service.updateById(entity);
|
return service.updateById(entity);
|
||||||
}
|
}
|
||||||
@@ -431,7 +431,7 @@ public final class MkProcessBizHandlers {
|
|||||||
}
|
}
|
||||||
entity.setApprovalStatus("returned");
|
entity.setApprovalStatus("returned");
|
||||||
entity.setCurrentNode("审核不通过");
|
entity.setCurrentNode("审核不通过");
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
return service.updateById(entity);
|
return service.updateById(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,7 +498,7 @@ public final class MkProcessBizHandlers {
|
|||||||
FormalSettlement updated = service.getById(id);
|
FormalSettlement updated = service.getById(id);
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
updated.setCurrentNode("审核通过");
|
updated.setCurrentNode("审核通过");
|
||||||
updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(updated);
|
service.updateById(updated);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -516,7 +516,7 @@ public final class MkProcessBizHandlers {
|
|||||||
}
|
}
|
||||||
entity.setApprovalStatus("returned");
|
entity.setApprovalStatus("returned");
|
||||||
entity.setCurrentNode("审核不通过");
|
entity.setCurrentNode("审核不通过");
|
||||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
return service.updateById(entity);
|
return service.updateById(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,7 +573,7 @@ public final class MkProcessBizHandlers {
|
|||||||
PaymentApplication updated = service.getById(id);
|
PaymentApplication updated = service.getById(id);
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
updated.setCurrentNode("审核通过");
|
updated.setCurrentNode("审核通过");
|
||||||
updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
// HCS 推送零埋点:MK 审批回调仅置待同步状态,与 /approve 入口收敛于同一权威状态(ADR-0001)
|
// HCS 推送零埋点:MK 审批回调仅置待同步状态,与 /approve 入口收敛于同一权威状态(ADR-0001)
|
||||||
updated.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
updated.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||||
service.updateById(updated);
|
service.updateById(updated);
|
||||||
@@ -600,7 +600,7 @@ public final class MkProcessBizHandlers {
|
|||||||
}
|
}
|
||||||
updated.setApprovalStatus("returned");
|
updated.setApprovalStatus("returned");
|
||||||
updated.setCurrentNode("审核不通过");
|
updated.setCurrentNode("审核不通过");
|
||||||
updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
return service.updateById(updated);
|
return service.updateById(updated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -654,7 +654,7 @@ public final class MkProcessBizHandlers {
|
|||||||
InvoiceApplication updated = service.getById(id);
|
InvoiceApplication updated = service.getById(id);
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
updated.setCurrentNode("审核通过");
|
updated.setCurrentNode("审核通过");
|
||||||
updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(updated);
|
service.updateById(updated);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -673,7 +673,7 @@ public final class MkProcessBizHandlers {
|
|||||||
InvoiceApplication updated = service.getById(id);
|
InvoiceApplication updated = service.getById(id);
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
updated.setCurrentNode("审核不通过");
|
updated.setCurrentNode("审核不通过");
|
||||||
updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(updated);
|
service.updateById(updated);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -729,7 +729,7 @@ public final class MkProcessBizHandlers {
|
|||||||
InvoiceReceipt updated = service.getById(id);
|
InvoiceReceipt updated = service.getById(id);
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
updated.setCurrentNode("审核通过");
|
updated.setCurrentNode("审核通过");
|
||||||
updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(updated);
|
service.updateById(updated);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -748,7 +748,7 @@ public final class MkProcessBizHandlers {
|
|||||||
InvoiceReceipt updated = service.getById(id);
|
InvoiceReceipt updated = service.getById(id);
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
updated.setCurrentNode("审核不通过");
|
updated.setCurrentNode("审核不通过");
|
||||||
updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(updated);
|
service.updateById(updated);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -804,7 +804,7 @@ public final class MkProcessBizHandlers {
|
|||||||
BillPayment updated = service.getById(id);
|
BillPayment updated = service.getById(id);
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
updated.setCurrentNode("审核通过");
|
updated.setCurrentNode("审核通过");
|
||||||
updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(updated);
|
service.updateById(updated);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -823,7 +823,7 @@ public final class MkProcessBizHandlers {
|
|||||||
BillPayment updated = service.getById(id);
|
BillPayment updated = service.getById(id);
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
updated.setCurrentNode("审核不通过");
|
updated.setCurrentNode("审核不通过");
|
||||||
updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
service.updateById(updated);
|
service.updateById(updated);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+16
@@ -20,6 +20,11 @@ public final class MkProcessNodeHelper {
|
|||||||
*/
|
*/
|
||||||
private static final String DRAFT_NODE_NUMBER = "N2";
|
private static final String DRAFT_NODE_NUMBER = "N2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程完结后业务单据「当前处理人」统一展示文案。
|
||||||
|
*/
|
||||||
|
public static final String PROCESS_FINISHED = "流程结束";
|
||||||
|
|
||||||
private static final List<String> CURRENT_NODE_KEYS = List.of("handlerInfos", "drafterInfos", "adminInfos");
|
private static final List<String> CURRENT_NODE_KEYS = List.of("handlerInfos", "drafterInfos", "adminInfos");
|
||||||
|
|
||||||
private MkProcessNodeHelper() {
|
private MkProcessNodeHelper() {
|
||||||
@@ -39,9 +44,20 @@ public final class MkProcessNodeHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String currentProcessor(Object processInfo) {
|
public static String currentProcessor(Object processInfo) {
|
||||||
|
// 流程已完结时不再回写最后处理人,统一展示「流程结束」
|
||||||
|
if (isProcessFinished(processInfo)) {
|
||||||
|
return PROCESS_FINISHED;
|
||||||
|
}
|
||||||
return joinDistinct(extractTexts(asMap(processInfo).get("currentHandlers"), "fdName", "name"), "、");
|
return joinDistinct(extractTexts(asMap(processInfo).get("currentHandlers"), "fdName", "name"), "、");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MK 流程是否已完结(fdProcessStatus=30)。
|
||||||
|
*/
|
||||||
|
public static boolean isProcessFinished(Object processInfo) {
|
||||||
|
return "30".equals(text(asMap(processInfo).get("fdProcessStatus")));
|
||||||
|
}
|
||||||
|
|
||||||
public static String currentNode(Object processInfo) {
|
public static String currentNode(Object processInfo) {
|
||||||
Map<String, Object> taskInfo = asMap(asMap(processInfo).get("fdTaskInfo"));
|
Map<String, Object> taskInfo = asMap(asMap(processInfo).get("fdTaskInfo"));
|
||||||
List<String> nodeNames = new ArrayList<>();
|
List<String> nodeNames = new ArrayList<>();
|
||||||
|
|||||||
+9
-3
@@ -280,9 +280,15 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
|||||||
public boolean submit(CustomerArchiveVO customer) {
|
public boolean submit(CustomerArchiveVO customer) {
|
||||||
CustomerArchiveVO beforeDetail = Func.isEmpty(customer.getId()) ? null : detail(customer.getId());
|
CustomerArchiveVO beforeDetail = Func.isEmpty(customer.getId()) ? null : detail(customer.getId());
|
||||||
prepare(customer);
|
prepare(customer);
|
||||||
validateBase(customer);
|
|
||||||
boolean created = Func.isEmpty(customer.getId());
|
boolean created = Func.isEmpty(customer.getId());
|
||||||
CustomerArchive before = created ? null : ensureCustomerAccessible(customer.getId());
|
CustomerArchive before = created ? null : ensureCustomerAccessible(customer.getId());
|
||||||
|
if (!created) {
|
||||||
|
// 编辑时客商编号、供应商编码、统一社会信用代码不允许修改
|
||||||
|
customer.setCustomerCode(before.getCustomerCode());
|
||||||
|
customer.setSupplierCode(before.getSupplierCode());
|
||||||
|
customer.setUnifiedCreditCode(before.getUnifiedCreditCode());
|
||||||
|
}
|
||||||
|
validateBase(customer);
|
||||||
if (created) {
|
if (created) {
|
||||||
// 新增时金蝶已有客商,前端回填金蝶客商编码,建档直接沿用;未回填则自动生成
|
// 新增时金蝶已有客商,前端回填金蝶客商编码,建档直接沿用;未回填则自动生成
|
||||||
customer.setCustomerCode(Func.isEmpty(customer.getCustomerCode()) ? this.nextCustomerCode() : customer.getCustomerCode());
|
customer.setCustomerCode(Func.isEmpty(customer.getCustomerCode()) ? this.nextCustomerCode() : customer.getCustomerCode());
|
||||||
@@ -432,7 +438,7 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
|||||||
after.setAccessType(ACCESS_FORMAL);
|
after.setAccessType(ACCESS_FORMAL);
|
||||||
after.setApprovalStatus(APPROVAL_APPROVED);
|
after.setApprovalStatus(APPROVAL_APPROVED);
|
||||||
after.setCurrentNode("审核通过");
|
after.setCurrentNode("审核通过");
|
||||||
after.setCurrentProcessor(Func.isEmpty(processorName) ? "系统" : processorName.trim());
|
after.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
after.setApprovedTime(LocalDateTime.now());
|
after.setApprovedTime(LocalDateTime.now());
|
||||||
// 审核通过后按当前未删除评分刷新生效等级/额度(替换旧评分场景在此切换生效)
|
// 审核通过后按当前未删除评分刷新生效等级/额度(替换旧评分场景在此切换生效)
|
||||||
this.applyCreditFromActiveScore(after);
|
this.applyCreditFromActiveScore(after);
|
||||||
@@ -462,7 +468,7 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
|||||||
CustomerArchive after = copyCustomer(before);
|
CustomerArchive after = copyCustomer(before);
|
||||||
after.setApprovalStatus(APPROVAL_REJECTED);
|
after.setApprovalStatus(APPROVAL_REJECTED);
|
||||||
after.setCurrentNode("审核不通过");
|
after.setCurrentNode("审核不通过");
|
||||||
after.setCurrentProcessor(Func.isEmpty(processorName) ? "系统" : processorName.trim());
|
after.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED);
|
||||||
addChangeRecord(id, "客商准入审核不通过", before, after);
|
addChangeRecord(id, "客商准入审核不通过", before, after);
|
||||||
boolean updated = updateById(after);
|
boolean updated = updateById(after);
|
||||||
log.info("流程审核驳回 id={} processor={} result={}", id, after.getCurrentProcessor(), updated);
|
log.info("流程审核驳回 id={} processor={} result={}", id, after.getCurrentProcessor(), updated);
|
||||||
|
|||||||
Reference in New Issue
Block a user