diff --git a/blade-service/blade-system/src/main/java/org/springblade/process/service/impl/BusinessProcessServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/process/service/impl/BusinessProcessServiceImpl.java index 42326194..b2a1e977 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/process/service/impl/BusinessProcessServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/process/service/impl/BusinessProcessServiceImpl.java @@ -415,7 +415,8 @@ public class BusinessProcessServiceImpl extends ServiceImpl + diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/IRoleMenuDataScopeService.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/IRoleMenuDataScopeService.java index 17349a22..434f8ec0 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/IRoleMenuDataScopeService.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/IRoleMenuDataScopeService.java @@ -41,7 +41,8 @@ import java.util.List; public interface IRoleMenuDataScopeService extends BaseService { /** - * 查询角色数据权限配置树 + * 查询角色数据权限配置树。 + * 菜单范围与该角色已保存的菜单权限一致,已配置的数据权限不会被清除。 * * @param roleId 角色主键 * @return 菜单树与已配置权限 @@ -57,11 +58,12 @@ public interface IRoleMenuDataScopeService extends BaseService roleIds, String menuCode, List userDeptIds); diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/IUserService.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/IUserService.java index e4160480..91e08fba 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/IUserService.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/IUserService.java @@ -401,4 +401,13 @@ public interface IUserService extends BaseService { * @param user 用户对象 */ void encryptPhone(IPhone user); + + /** + * 首次同步时初始化数据管理组织;已有配置则跳过更新。 + * + * @param userId 用户主键 + * @param deptIds 所属组织 ID 集合 + * @return 是否成功 + */ + boolean initManageDeptScopeIfAbsent(Long userId, List deptIds); } diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DeptServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DeptServiceImpl.java index ad2bd919..b8c33b46 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DeptServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DeptServiceImpl.java @@ -49,6 +49,7 @@ import org.springblade.system.mapper.DeptMapper; import org.springblade.system.pojo.entity.Dept; import org.springblade.system.pojo.entity.User; 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.RoleDataScopeVO; import org.springblade.system.pojo.vo.UserVO; @@ -271,6 +272,15 @@ public class DeptServiceImpl extends ServiceImpl implements ID allowedDeptIds.add(deptId); } } + } else if (RoleDataScopeType.DEPT_AND_CHILD.matches(scope.getScopeType())) { + // 所在部门及下级按用户数据权限组织,不按所属组织展开 + if (Func.isNotEmpty(scope.getDeptIds())) { + allowedDeptIds.addAll(scope.getDeptIds()); + } + List manageDeptIds = userService.resolveManageDeptIds(userId); + if (Func.isNotEmpty(manageDeptIds)) { + allowedDeptIds.addAll(manageDeptIds); + } } else if (Func.isNotEmpty(scope.getDeptIds())) { allowedDeptIds.addAll(scope.getDeptIds()); } diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/OaUserListSyncHelper.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/OaUserListSyncHelper.java index a99147a6..fbc8e141 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/OaUserListSyncHelper.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/OaUserListSyncHelper.java @@ -34,6 +34,7 @@ import org.springblade.common.constant.CommonConstant; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.constant.BladeConstant; import org.springblade.core.tool.utils.DigestUtil; +import org.springblade.core.tool.utils.Func; import org.springblade.system.cache.ParamCache; import org.springblade.system.convert.UserConvert; import org.springblade.system.log.ComposeLogUtil; @@ -790,6 +791,21 @@ public class OaUserListSyncHelper { if (CollectionUtil.isNotEmpty(updateUserParams)) { userService.updateBatchById(updateUserParams); } + // 首次同步:数据管理组织=所属组织;已有数据管理组织的用户下次同步跳过 + Set 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 deptIdList = Func.toLongList(userDeptIds.getDeptIds()); + if (Func.isEmpty(deptIdList)) { + continue; + } + userService.initManageDeptScopeIfAbsent(userDeptIds.getUserId(), deptIdList); + } return new PersonSyncCount(syncedCount, skippedCount, removedCount); } diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/RoleMenuDataScopeServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/RoleMenuDataScopeServiceImpl.java index 04d62d5b..c9b3cef5 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/RoleMenuDataScopeServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/RoleMenuDataScopeServiceImpl.java @@ -34,13 +34,14 @@ import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.node.ForestNodeMerger; import org.springblade.core.tool.node.TreeNode; import org.springblade.core.tool.utils.Func; -import org.springblade.system.cache.SysCache; import org.springblade.system.mapper.MenuMapper; import org.springblade.system.mapper.RoleMenuDataScopeDeptMapper; import org.springblade.system.mapper.RoleMenuDataScopeMapper; +import org.springblade.system.mapper.RoleMenuMapper; import org.springblade.system.pojo.dto.RoleMenuDataScopeDTO; import org.springblade.system.pojo.entity.Menu; 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.RoleMenuDataScopeDept; import org.springblade.system.pojo.enums.RoleDataScopeType; @@ -58,6 +59,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE; @@ -74,6 +76,7 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl menuNodes = menuMapper.grantTree(); + // 数据权限菜单与已保存的菜单权限保持一致;这里只收窄展示范围,不删除已有数据权限配置 + List menuNodes = filterGrantedMenus(menuMapper.grantTree(), roleId); treeVO.setMenuTree(ForestNodeMerger.merge(menuNodes)); List scopeList = list(Wrappers.lambdaQuery() @@ -189,7 +193,7 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl scopeList = listScopes(roleIds, menu.getId()); - return mergeScopes(scopeList, userDeptIds); + return mergeScopes(scopeList); } @Override @@ -205,7 +209,45 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl filterGrantedMenus(List menuNodes, Long roleId) { + if (Func.isEmpty(menuNodes)) { + return Collections.emptyList(); + } + Set grantedMenuIds = roleMenuMapper.selectList(Wrappers.lambdaQuery() + .eq(RoleMenu::getRoleId, roleId)) + .stream() + .map(RoleMenu::getMenuId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + if (grantedMenuIds.isEmpty()) { + return Collections.emptyList(); + } + Map parentMap = menuNodes.stream() + .filter(node -> node.getId() != null) + .collect(Collectors.toMap(TreeNode::getId, TreeNode::getParentId, (left, right) -> left)); + Set 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) { @@ -230,30 +272,33 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl scopeList = list(Wrappers.lambdaQuery() .in(RoleMenuDataScope::getRoleId, roleIds) .eq(RoleMenuDataScope::getIsDeleted, 0)); - return mergeScopes(scopeList, userDeptIds); + return mergeScopes(scopeList); } - private RoleDataScopeVO mergeScopes(List scopeList, List userDeptIds) { + /** + * 合并多条角色菜单数据权限。 + * 全部组织、本人创建优先于组织范围;所在部门及下级不在此处展开所属组织, + * 由调用方替换为用户的数据权限组织。 + */ + private RoleDataScopeVO mergeScopes(List scopeList) { if (Func.isEmpty(scopeList)) { return RoleDataScopeVO.all(); } boolean hasAll = false; - boolean hasDeptScope = false; + boolean hasDeptAndChild = false; + boolean hasCustom = false; boolean hasOwn = false; - LinkedHashSet allowedDeptIds = new LinkedHashSet<>(); + LinkedHashSet customDeptIds = new LinkedHashSet<>(); Map> customDeptMap = loadCustomDeptMap(scopeList); for (RoleMenuDataScope scope : scopeList) { RoleDataScopeType type = RoleDataScopeType.of(scope.getScopeType()); switch (type) { case ALL -> hasAll = true; - case DEPT_AND_CHILD -> { - hasDeptScope = true; - allowedDeptIds.addAll(expandDeptIds(userDeptIds, true)); - } + case DEPT_AND_CHILD -> hasDeptAndChild = true; case CUSTOM -> { - hasDeptScope = true; - allowedDeptIds.addAll(customDeptMap.getOrDefault(scope.getId(), Collections.emptyList())); + hasCustom = true; + customDeptIds.addAll(customDeptMap.getOrDefault(scope.getId(), Collections.emptyList())); } case OWN_CREATE -> hasOwn = true; default -> { @@ -263,8 +308,11 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl(allowedDeptIds)); + if (hasDeptAndChild) { + return RoleDataScopeVO.ofDepts(RoleDataScopeType.DEPT_AND_CHILD.getCode(), new ArrayList<>(customDeptIds)); + } + if (hasCustom) { + return RoleDataScopeVO.ofDepts(RoleDataScopeType.CUSTOM.getCode(), new ArrayList<>(customDeptIds)); } if (hasOwn) { return RoleDataScopeVO.ownCreate(); @@ -287,26 +335,4 @@ public class RoleMenuDataScopeServiceImpl extends BaseServiceImpl expandDeptIds(List baseDeptIds, boolean includeChildren) { - if (Func.isEmpty(baseDeptIds)) { - return Collections.emptyList(); - } - LinkedHashSet result = new LinkedHashSet<>(); - for (Long deptId : baseDeptIds) { - if (Func.isEmpty(deptId) || deptId <= 0) { - continue; - } - if (includeChildren) { - List childIds = SysCache.getDeptChildIds(deptId); - if (Func.isNotEmpty(childIds)) { - result.addAll(childIds); - } else { - result.add(deptId); - } - } else { - result.add(deptId); - } - } - return new ArrayList<>(result); - } } diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/UserServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/UserServiceImpl.java index 67122919..75c1f545 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/UserServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/UserServiceImpl.java @@ -256,6 +256,8 @@ public class UserServiceImpl extends BaseServiceImpl implement user.setStatus(status); user.setIsOa(1); user.setSyncTime(new Date()); + // 首次同步:数据管理组织默认等于所属组织 + user.setDataScopeDeptIds(Func.toLongList(user.getDeptId())); applyUserDefaults(user); return saveUser(user); } @@ -326,6 +328,7 @@ public class UserServiceImpl extends BaseServiceImpl implement if (userCount > 0L) { throw new ServiceException(StringUtil.format("当前用户 [{}] 已存在!", user.getAccount())); } + encryptPhone(user); Long phoneCount = baseMapper.selectCount( Wrappers.query().lambda() .eq(User::getTenantId, tenantId) @@ -373,6 +376,7 @@ public class UserServiceImpl extends BaseServiceImpl implement } private boolean submitUserInfo(User user) { + encryptPhone(user); Long phoneCount = baseMapper.selectCount( Wrappers.query().lambda() .eq(User::getTenantId, AuthUtil.getTenantId()) @@ -736,6 +740,7 @@ public class UserServiceImpl extends BaseServiceImpl implement public List exportUser(Wrapper queryWrapper) { List userList = baseMapper.exportUser(queryWrapper); userList.forEach(user -> { + decryptPhone(user); user.setUserTypeName(DictCache.getValue(DictEnum.USER_TYPE, user.getUserType())); user.setRoleName(StringUtil.join(SysCache.getRoleNames(user.getRoleId()))); user.setDeptName(StringUtil.join(SysCache.getDeptNames(user.getDeptId()))); @@ -1105,6 +1110,7 @@ public class UserServiceImpl extends BaseServiceImpl implement } validatePlainPassword(user.getPassword()); user.setPassword(DigestUtil.encrypt(user.getPassword())); + encryptPhone(user); Long userCount = baseMapper.selectCount(Wrappers.query().lambda().eq(User::getTenantId, tenantId).eq(User::getAccount, user.getAccount())); if (userCount > 0L && Func.isEmpty(user.getId())) { throw new ServiceException(StringUtil.format("当前用户 [{}] 已存在!", user.getAccount())); @@ -1301,9 +1307,45 @@ public class UserServiceImpl extends BaseServiceImpl implement if (user == null) { return; } - if (StringUtil.isNotBlank(user.getPhone())) { - user.setPhone(Hex.toHexString(SM2Util.encrypt(user.getPhone(), properties.getPublicKey()))); + String phone = user.getPhone(); + 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 deptIds) { + if (Func.isEmpty(userId) || userId <= 0 || Func.isEmpty(deptIds)) { + return true; + } + Long existsCount = userDataScopeMapper.selectCount(Wrappers.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) { diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/wrapper/UserWrapper.java b/blade-service/blade-system/src/main/java/org/springblade/system/wrapper/UserWrapper.java index 3630589b..f4b9340e 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/wrapper/UserWrapper.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/wrapper/UserWrapper.java @@ -28,6 +28,7 @@ package org.springblade.system.wrapper; import org.springblade.core.mp.support.BaseEntityWrapper; import org.springblade.core.tool.utils.BeanUtil; 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.StringUtil; 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.enums.DictEnum; import org.springblade.system.pojo.vo.UserVO; +import org.springblade.system.service.IUserService; import java.util.List; import java.util.Objects; @@ -57,6 +59,8 @@ public class UserWrapper extends BaseEntityWrapper { if (userVO == null) { return null; } + // 列表/详情展示解密后的明文手机号,避免 SM2 密文被当成手机号脱敏成乱码 + SpringUtil.getBean(IUserService.class).decryptPhone(userVO); Tenant tenant = SysCache.getTenant(user.getTenantId()); if (tenant != null) { userVO.setTenantName(tenant.getTenantName()); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mk/MkProcessBizHandlers.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/mk/MkProcessBizHandlers.java index 296dfbfc..09a20566 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mk/MkProcessBizHandlers.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mk/MkProcessBizHandlers.java @@ -128,7 +128,7 @@ public final class MkProcessBizHandlers { entity.setApprovalStatus(change ? "change_approved" : "approved"); entity.setEffectiveType("formal"); entity.setCurrentNode("审核通过"); - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); entity.setApprovedTime(LocalDateTime.now()); // HCS 推送:审批通过置待同步状态,更新成功后即时推送,扫描任务保留兜底(ADR-0001 修订,前端接入设计 §6) entity.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED); @@ -149,7 +149,7 @@ public final class MkProcessBizHandlers { boolean change = "change_reviewing".equals(entity.getApprovalStatus()); entity.setApprovalStatus(change ? "change_rejected" : "rejected"); entity.setCurrentNode("审核不通过"); - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); return service.updateById(entity); } } @@ -201,7 +201,7 @@ public final class MkProcessBizHandlers { Long projectId = service.approve(id); entity = service.getById(id); if (entity != null) { - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(entity); } if (projectId != null) { @@ -219,7 +219,7 @@ public final class MkProcessBizHandlers { boolean rejected = service.reject(id); entity = service.getById(id); if (entity != null) { - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(entity); } return rejected; @@ -273,7 +273,7 @@ public final class MkProcessBizHandlers { Long contractId = service.approve(id); entity = service.getById(id); if (entity != null) { - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(entity); } if (contractId != null) { @@ -291,7 +291,7 @@ public final class MkProcessBizHandlers { boolean rejected = service.reject(id); entity = service.getById(id); if (entity != null) { - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(entity); } return rejected; @@ -348,7 +348,7 @@ public final class MkProcessBizHandlers { boolean change = "change_reviewing".equals(entity.getApprovalStatus()); entity.setApprovalStatus(change ? "change_approved" : "approved"); entity.setCurrentNode("审核通过"); - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); // HCS 推送:审批通过置待同步状态,更新成功后即时推送,扫描任务保留兜底(ADR-0001 修订,前端接入设计 §6) entity.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED); boolean updated = service.updateById(entity); @@ -368,7 +368,7 @@ public final class MkProcessBizHandlers { boolean change = "change_reviewing".equals(entity.getApprovalStatus()); entity.setApprovalStatus(change ? "change_rejected" : "rejected"); entity.setCurrentNode("审核不通过"); - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); return service.updateById(entity); } } @@ -418,7 +418,7 @@ public final class MkProcessBizHandlers { } entity.setApprovalStatus("approved"); entity.setCurrentNode("审核通过"); - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); entity.setApprovedTime(LocalDateTime.now()); return service.updateById(entity); } @@ -431,7 +431,7 @@ public final class MkProcessBizHandlers { } entity.setApprovalStatus("returned"); entity.setCurrentNode("审核不通过"); - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); return service.updateById(entity); } } @@ -498,7 +498,7 @@ public final class MkProcessBizHandlers { FormalSettlement updated = service.getById(id); if (updated != null) { updated.setCurrentNode("审核通过"); - updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(updated); } return true; @@ -516,7 +516,7 @@ public final class MkProcessBizHandlers { } entity.setApprovalStatus("returned"); entity.setCurrentNode("审核不通过"); - entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + entity.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); return service.updateById(entity); } } @@ -573,7 +573,7 @@ public final class MkProcessBizHandlers { PaymentApplication updated = service.getById(id); if (updated != null) { updated.setCurrentNode("审核通过"); - updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); // HCS 推送零埋点:MK 审批回调仅置待同步状态,与 /approve 入口收敛于同一权威状态(ADR-0001) updated.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED); service.updateById(updated); @@ -600,7 +600,7 @@ public final class MkProcessBizHandlers { } updated.setApprovalStatus("returned"); updated.setCurrentNode("审核不通过"); - updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); return service.updateById(updated); } } @@ -654,7 +654,7 @@ public final class MkProcessBizHandlers { InvoiceApplication updated = service.getById(id); if (updated != null) { updated.setCurrentNode("审核通过"); - updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(updated); } return true; @@ -673,7 +673,7 @@ public final class MkProcessBizHandlers { InvoiceApplication updated = service.getById(id); if (updated != null) { updated.setCurrentNode("审核不通过"); - updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(updated); } return true; @@ -729,7 +729,7 @@ public final class MkProcessBizHandlers { InvoiceReceipt updated = service.getById(id); if (updated != null) { updated.setCurrentNode("审核通过"); - updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(updated); } return true; @@ -748,7 +748,7 @@ public final class MkProcessBizHandlers { InvoiceReceipt updated = service.getById(id); if (updated != null) { updated.setCurrentNode("审核不通过"); - updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(updated); } return true; @@ -804,7 +804,7 @@ public final class MkProcessBizHandlers { BillPayment updated = service.getById(id); if (updated != null) { updated.setCurrentNode("审核通过"); - updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(updated); } return true; @@ -823,7 +823,7 @@ public final class MkProcessBizHandlers { BillPayment updated = service.getById(id); if (updated != null) { updated.setCurrentNode("审核不通过"); - updated.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统")); + updated.setCurrentProcessor(MkProcessNodeHelper.PROCESS_FINISHED); service.updateById(updated); } return true; diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mk/MkProcessNodeHelper.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/mk/MkProcessNodeHelper.java index 6004bbb0..eaef160e 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mk/MkProcessNodeHelper.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mk/MkProcessNodeHelper.java @@ -20,6 +20,11 @@ public final class MkProcessNodeHelper { */ private static final String DRAFT_NODE_NUMBER = "N2"; + /** + * 流程完结后业务单据「当前处理人」统一展示文案。 + */ + public static final String PROCESS_FINISHED = "流程结束"; + private static final List CURRENT_NODE_KEYS = List.of("handlerInfos", "drafterInfos", "adminInfos"); private MkProcessNodeHelper() { @@ -39,9 +44,20 @@ public final class MkProcessNodeHelper { } public static String currentProcessor(Object processInfo) { + // 流程已完结时不再回写最后处理人,统一展示「流程结束」 + if (isProcessFinished(processInfo)) { + return PROCESS_FINISHED; + } 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) { Map taskInfo = asMap(asMap(processInfo).get("fdTaskInfo")); List nodeNames = new ArrayList<>(); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java index e576612c..4aa8eac6 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java @@ -280,9 +280,15 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl