Pārlūkot izejas kodu

feat: 5项需求改动

- 我的待办默认按创建时间升序
- 我的待办增加流程字段筛选抽屉
- 审批通过时展示分支/节点名称
- 移除审批角色页面的企微配置按钮及相关代码
- 审批角色列表按创建时间从新到旧排序
ye-zhaojia 1 nedēļu atpakaļ
vecāks
revīzija
8924470109

+ 3 - 2
src/main/java/com/qqflow/engine/domain/flow/controller/ApprovalTaskController.java

@@ -40,10 +40,11 @@ public class ApprovalTaskController {
     public Result<PageResult<ApprovalTaskDTO>> todoList(
             @RequestParam(defaultValue = "1") Integer pageNum,
             @RequestParam(defaultValue = "10") Integer pageSize,
-            @RequestParam(required = false) String processName) {
+            @RequestParam(required = false) String processName,
+            @RequestParam(required = false) String formFilters) {
         Long assigneeId = SecurityUtils.getUserId();
         String assigneeType = requireLoginUser().getUserType();
-        return Result.ok(this.approvalTaskService.todoList(assigneeId, assigneeType, processName, pageNum, pageSize));
+        return Result.ok(this.approvalTaskService.todoList(assigneeId, assigneeType, processName, formFilters, pageNum, pageSize));
     }
 
     @GetMapping("/handled")

+ 6 - 0
src/main/java/com/qqflow/engine/domain/flow/dto/NextNodeDTO.java

@@ -15,4 +15,10 @@ public class NextNodeDTO {
 
     @Schema(description = "节点类型")
     private String nodeType;
+
+    @Schema(description = "分支名称(条件分支场景)")
+    private String branchName;
+
+    @Schema(description = "分支条件表达式")
+    private String condition;
 }

+ 3 - 1
src/main/java/com/qqflow/engine/domain/flow/mapper/ApprovalTaskMapper.java

@@ -8,6 +8,7 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
 import java.util.List;
+import java.util.Map;
 
 @Mapper
 public interface ApprovalTaskMapper extends BaseMapper<ApprovalTask> {
@@ -33,7 +34,8 @@ public interface ApprovalTaskMapper extends BaseMapper<ApprovalTask> {
             @Param("assigneeId") Long assigneeId,
             @Param("assigneeType") String assigneeType,
             @Param("roleIds") List<Long> roleIds,
-            @Param("processName") String processName);
+            @Param("processName") String processName,
+            @Param("formFilters") Map<String, String> formFilters);
 
     com.baomidou.mybatisplus.extension.plugins.pagination.Page<ApprovalTask> selectHandledList(
             com.baomidou.mybatisplus.extension.plugins.pagination.Page<ApprovalTask> page,

+ 1 - 1
src/main/java/com/qqflow/engine/domain/flow/service/ApprovalTaskService.java

@@ -13,7 +13,7 @@ import java.util.List;
 
 public interface ApprovalTaskService {
 
-    PageResult<ApprovalTaskDTO> todoList(Long assigneeId, String assigneeType, String processName, Integer pageNum, Integer pageSize);
+    PageResult<ApprovalTaskDTO> todoList(Long assigneeId, String assigneeType, String processName, String formFilters, Integer pageNum, Integer pageSize);
 
     PageResult<ApprovalTaskDTO> handledList(Long assigneeId, String assigneeType, String processName, Integer pageNum, Integer pageSize);
 

+ 51 - 10
src/main/java/com/qqflow/engine/domain/flow/service/impl/ApprovalTaskServiceImpl.java

@@ -44,12 +44,14 @@ import com.qqflow.engine.domain.system.mapper.SysUserMapper;
 import com.qqflow.engine.domain.system.mapper.SysUserRoleMapper;
 import com.qqflow.engine.domain.system.service.SysUserService;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.ApplicationEventPublisher;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 
 import java.io.File;
 import java.time.LocalDateTime;
@@ -67,6 +69,7 @@ import static com.qqflow.engine.common.constant.SecurityConstants.ROLE_SUPER_ADM
 import static com.qqflow.engine.common.constant.SecurityConstants.USER_TYPE_ROLE;
 import static com.qqflow.engine.common.constant.SecurityConstants.USER_TYPE_SYSTEM;
 
+@Slf4j
 @Service
 @RequiredArgsConstructor
 public class ApprovalTaskServiceImpl implements ApprovalTaskService {
@@ -89,10 +92,11 @@ public class ApprovalTaskServiceImpl implements ApprovalTaskService {
     private final SysUserService sysUserService;
 
     @Override
-    public PageResult<ApprovalTaskDTO> todoList(Long assigneeId, String assigneeType, String processName, Integer pageNum, Integer pageSize) {
+    public PageResult<ApprovalTaskDTO> todoList(Long assigneeId, String assigneeType, String processName, String formFilters, Integer pageNum, Integer pageSize) {
         List<Long> roleIds = loadRoleIdsIfSystemUser(assigneeId, assigneeType);
         Page<ApprovalTask> page = new Page<>(pageNum, pageSize);
-        this.approvalTaskMapper.selectTodoList(page, assigneeId, assigneeType, roleIds, processName);
+        Map<String, String> filterMap = this.parseFormFilters(formFilters);
+        this.approvalTaskMapper.selectTodoList(page, assigneeId, assigneeType, roleIds, processName, filterMap);
         List<ApprovalTaskDTO> records = page.getRecords().stream()
                 .map(ApprovalTaskDTO::of)
                 .peek(this::fillUrgency)
@@ -101,6 +105,18 @@ public class ApprovalTaskServiceImpl implements ApprovalTaskService {
         return PageResult.of(page.getTotal(), records);
     }
 
+    private Map<String, String> parseFormFilters(String formFilters) {
+        if (!StringUtils.hasText(formFilters)) {
+            return Collections.emptyMap();
+        }
+        try {
+            return this.objectMapper.readValue(formFilters, new TypeReference<Map<String, String>>() {});
+        } catch (Exception e) {
+            log.warn("解析表单筛选条件失败: {}", e.getMessage());
+            return Collections.emptyMap();
+        }
+    }
+
     private void fillUrgency(ApprovalTaskDTO dto) {
         if (dto == null || dto.getTimeoutTime() == null) {
             dto.setUrgency(0);
@@ -573,16 +589,41 @@ public class ApprovalTaskServiceImpl implements ApprovalTaskService {
         if (definition == null) throw new BusinessException("流程定义不存在");
         FlowModel model = this.flowEngineService.parseModel(definition.getModelJson());
         // 返回所有下游节点(忽略条件),审批人手动选分支
-        return this.flowEngineService.getNextNodes(model, task.getNodeId()).stream()
+        List<FlowNode> nextNodes = this.flowEngineService.getNextNodes(model, task.getNodeId()).stream()
                 .filter(n -> !NodeType.START.getCode().equals(n.getType())
                         && !NodeType.END.getCode().equals(n.getType()))
-                .map(n -> {
-                    NextNodeDTO dto = new NextNodeDTO();
-                    dto.setNodeId(n.getId());
-                    dto.setNodeName(n.getName());
-                    dto.setNodeType(n.getType());
-                    return dto;
-                }).collect(Collectors.toList());
+                .collect(Collectors.toList());
+        if (model.getEdges() == null) {
+            return nextNodes.stream().map(this::buildNextNodeDto).collect(Collectors.toList());
+        }
+        return nextNodes.stream().map(n -> {
+            NextNodeDTO dto = this.buildNextNodeDto(n);
+            model.getEdges().stream()
+                    .filter(e -> Objects.equals(e.getSourceNodeId(), task.getNodeId())
+                            && Objects.equals(e.getTargetNodeId(), n.getId()))
+                    .findFirst()
+                    .ifPresent(edge -> {
+                        if (edge.getCondition() != null) {
+                            Object branchName = edge.getCondition().get("branchName");
+                            Object condition = edge.getCondition().get("condition");
+                            if (branchName != null) {
+                                dto.setBranchName(branchName.toString());
+                            }
+                            if (condition != null) {
+                                dto.setCondition(condition.toString());
+                            }
+                        }
+                    });
+            return dto;
+        }).collect(Collectors.toList());
+    }
+
+    private NextNodeDTO buildNextNodeDto(FlowNode node) {
+        NextNodeDTO dto = new NextNodeDTO();
+        dto.setNodeId(node.getId());
+        dto.setNodeName(StringUtils.hasText(node.getName()) ? node.getName() : node.getId());
+        dto.setNodeType(node.getType());
+        return dto;
     }
 
     @Override

+ 18 - 5
src/main/java/com/qqflow/engine/domain/flow/service/impl/WeComNotificationService.java

@@ -4,10 +4,10 @@ import com.qqflow.engine.domain.ewechat.service.EnterpriseWechatMsgService;
 import com.qqflow.engine.domain.flow.po.ApprovalTask;
 import com.qqflow.engine.domain.flow.service.NotificationService;
 import com.qqflow.engine.domain.system.dto.WeComConfigDTO;
-import com.qqflow.engine.domain.system.entity.SysRole;
 import com.qqflow.engine.domain.system.entity.SysUser;
-import com.qqflow.engine.domain.system.mapper.SysRoleMapper;
+import com.qqflow.engine.domain.system.entity.SysUserRole;
 import com.qqflow.engine.domain.system.mapper.SysUserMapper;
+import com.qqflow.engine.domain.system.mapper.SysUserRoleMapper;
 import com.qqflow.engine.domain.system.service.SysNotificationConfigService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -24,7 +24,7 @@ public class WeComNotificationService implements NotificationService {
     private static final String ASSIGNEE_TYPE_ROLE = "ROLE";
 
     private final SysUserMapper sysUserMapper;
-    private final SysRoleMapper sysRoleMapper;
+    private final SysUserRoleMapper sysUserRoleMapper;
     private final SysNotificationConfigService sysNotificationConfigService;
     private final EnterpriseWechatMsgService wechatMsgService;
 
@@ -71,9 +71,22 @@ public class WeComNotificationService implements NotificationService {
     }
 
     private String resolveWeComUserId(Long assigneeId, String assigneeType) {
+        // 企微通知按用户维度发送:角色任务取该角色下第一个有企微账号的用户
         if (ASSIGNEE_TYPE_ROLE.equalsIgnoreCase(assigneeType)) {
-            SysRole role = sysRoleMapper.selectById(assigneeId);
-            return role != null ? role.getWecomUserId() : null;
+            List<SysUserRole> userRoles = this.sysUserRoleMapper.selectList(
+                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysUserRole>()
+                            .eq(SysUserRole::getRoleId, assigneeId));
+            if (userRoles.isEmpty()) {
+                return null;
+            }
+            List<Long> userIds = userRoles.stream().map(SysUserRole::getUserId).distinct().toList();
+            List<SysUser> users = this.sysUserMapper.selectBatchIds(userIds);
+            for (SysUser user : users) {
+                if (user.getWecomUserId() != null && !user.getWecomUserId().isBlank()) {
+                    return user.getWecomUserId();
+                }
+            }
+            return null;
         }
         SysUser user = sysUserMapper.selectById(assigneeId);
         return user != null ? user.getWecomUserId() : null;

+ 0 - 8
src/main/java/com/qqflow/engine/domain/system/controller/SysRoleController.java

@@ -5,7 +5,6 @@ import com.qqflow.engine.common.PageResult;
 import com.qqflow.engine.common.Result;
 import com.qqflow.engine.domain.system.assembler.RoleAssembler;
 import com.qqflow.engine.domain.system.assembler.UserAssembler;
-import com.qqflow.engine.domain.system.dto.BindWeComDTO;
 import com.qqflow.engine.domain.system.dto.RoleDTO;
 import com.qqflow.engine.domain.system.dto.UserDTO;
 import com.qqflow.engine.domain.system.entity.SysDept;
@@ -145,11 +144,4 @@ public class SysRoleController {
         return Result.ok();
     }
 
-    @Operation(summary = "绑定/解绑角色企业微信账号")
-    @PutMapping("/{id}/wecom")
-    @PreAuthorize("hasRole('super_admin')")
-    public Result<Void> bindWeCom(@PathVariable Long id, @RequestBody BindWeComDTO dto) {
-        sysRoleService.bindWeCom(id, dto.getWecomUserId(), dto.getWecomRemindEnabled());
-        return Result.ok();
-    }
 }

+ 0 - 8
src/main/java/com/qqflow/engine/domain/system/dto/RoleDTO.java

@@ -34,12 +34,6 @@ public class RoleDTO {
     @Schema(description = "状态:0-禁用 1-正常")
     private Integer status;
 
-    @Schema(description = "企业微信用户ID")
-    private String wecomUserId;
-
-    @Schema(description = "是否开启企微提醒:0-否 1-是")
-    private Integer wecomRemindEnabled;
-
     @Schema(description = "创建时间")
     private LocalDateTime createTime;
 
@@ -55,8 +49,6 @@ public class RoleDTO {
         dto.setParentId(role.getParentId());
         dto.setDeptId(role.getDeptId());
         dto.setStatus(role.getStatus());
-        dto.setWecomUserId(role.getWecomUserId());
-        dto.setWecomRemindEnabled(role.getWecomRemindEnabled());
         dto.setCreateTime(role.getCreateTime());
         return dto;
     }

+ 0 - 6
src/main/java/com/qqflow/engine/domain/system/entity/SysRole.java

@@ -35,12 +35,6 @@ public class SysRole {
     @Schema(description = "状态:0-禁用 1-正常")
     private Integer status;
 
-    @Schema(description = "企业微信用户ID")
-    private String wecomUserId;
-
-    @Schema(description = "是否开启企微提醒:0-否 1-是")
-    private Integer wecomRemindEnabled;
-
     @Schema(description = "创建时间")
     private LocalDateTime createTime;
 }

+ 0 - 2
src/main/java/com/qqflow/engine/domain/system/service/SysRoleService.java

@@ -19,6 +19,4 @@ public interface SysRoleService extends IService<SysRole> {
     Page<SysRole> pageRoles(Page<SysRole> page, Long deptId, String roleCode, String roleName);
 
     List<SysRole> listRolesByUserId(Long userId);
-
-    void bindWeCom(Long id, String wecomUserId, Integer wecomRemindEnabled);
 }

+ 1 - 14
src/main/java/com/qqflow/engine/domain/system/service/impl/SysRoleServiceImpl.java

@@ -85,6 +85,7 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole>
         if (roleName != null && !roleName.isEmpty()) {
             wrapper.like(SysRole::getRoleName, roleName);
         }
+        wrapper.orderByDesc(SysRole::getCreateTime);
         return this.page(page, wrapper);
     }
 
@@ -92,18 +93,4 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole>
     public List<SysRole> listRolesByUserId(Long userId) {
         return this.baseMapper.selectRolesByUserId(userId);
     }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void bindWeCom(Long id, String wecomUserId, Integer wecomRemindEnabled) {
-        SysRole role = this.getById(id);
-        if (role == null) {
-            throw new BusinessException("角色不存在");
-        }
-        SysRole update = new SysRole();
-        update.setId(id);
-        update.setWecomUserId(wecomUserId);
-        update.setWecomRemindEnabled(wecomRemindEnabled);
-        this.updateById(update);
-    }
 }

+ 8 - 1
src/main/resources/mapper/flow/ApprovalTaskMapper.xml

@@ -54,7 +54,14 @@
         <if test="processName != null and processName != ''">
             AND pd.process_name LIKE CONCAT('%', #{processName}, '%')
         </if>
-        ORDER BY t.create_time DESC
+        <if test="formFilters != null and formFilters.size() > 0">
+            <foreach collection="formFilters" index="key" item="value">
+                <if test="value != null and value != ''">
+                    AND pi.form_data LIKE CONCAT('"%', #{key}, '%"%', #{value}, '%')
+                </if>
+            </foreach>
+        </if>
+        ORDER BY t.create_time ASC
     </select>
 
     <select id="selectHandledList" resultMap="BaseResultMap">