⚡ 优化角色数据权限、用户组织范围与流程完结处理人展示

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-09 22:55:11 +08:00
co-authored by Cursor
parent 2ab7b893fd
commit 719d09fde2
13 changed files with 280 additions and 96 deletions
@@ -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())
@@ -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;
@@ -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 &lt;&gt; 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 &lt;&gt; 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>
@@ -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);
@@ -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);
} }
@@ -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());
} }
@@ -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);
} }
@@ -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);
}
} }
@@ -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) {
@@ -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());
@@ -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;
@@ -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<>();
@@ -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);