update 还原待办任务,添加待办消息发送

This commit is contained in:
songgaoshuai 2023-10-24 13:40:28 +08:00
parent 7d6d1ade4f
commit 06bf090b52
10 changed files with 162 additions and 131 deletions

View File

@ -53,6 +53,21 @@
<artifactId>ruoyi-system</artifactId> <artifactId>ruoyi-system</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mail</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-sms</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,31 @@
package org.dromara.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 消息类型枚举
*
* @author may
*/
@Getter
@AllArgsConstructor
public enum MessageTypeEnum {
/**
* 站内信
*/
SYSTEM_MESSAGE("1", "站内信"),
/**
* 邮箱
*/
EMAIL_MESSAGE("2", "邮箱"),
/**
* 短信
*/
SMS_MESSAGE("3", "短信");
private final String code;
private final String desc;
}

View File

@ -6,6 +6,7 @@ import org.dromara.common.core.validate.AddGroup;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
/** /**
@ -25,6 +26,11 @@ public class BackProcessBo implements Serializable {
@NotBlank(message = "任务ID不能为空", groups = AddGroup.class) @NotBlank(message = "任务ID不能为空", groups = AddGroup.class)
private String taskId; private String taskId;
/**
* 消息类型
*/
private List<String> messageType;
/** /**
* 驳回的节点id(目前未使用直接驳回到申请人) * 驳回的节点id(目前未使用直接驳回到申请人)
*/ */

View File

@ -7,6 +7,7 @@ import org.dromara.common.core.validate.AddGroup;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -27,6 +28,11 @@ public class CompleteTaskBo implements Serializable {
@NotBlank(message = "任务id不能为空", groups = {AddGroup.class}) @NotBlank(message = "任务id不能为空", groups = {AddGroup.class})
private String taskId; private String taskId;
/**
* 消息类型
*/
private List<String> messageType;
/** /**
* 办理意见 * 办理意见
*/ */

View File

@ -1,5 +1,6 @@
package org.dromara.workflow.mapper; package org.dromara.workflow.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.dromara.workflow.domain.ActHiProcinst; import org.dromara.workflow.domain.ActHiProcinst;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
@ -9,6 +10,7 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
* @author may * @author may
* @date 2023-07-22 * @date 2023-07-22
*/ */
@InterceptorIgnore(tenantLine = "true")
public interface ActHiProcinstMapper extends BaseMapperPlus<ActHiProcinst, ActHiProcinst> { public interface ActHiProcinstMapper extends BaseMapperPlus<ActHiProcinst, ActHiProcinst> {
} }

View File

@ -1,30 +0,0 @@
package org.dromara.workflow.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.workflow.domain.vo.TaskVo;
import java.util.List;
/**
* 运行时任务Mapper接口
*
* @author may
* @date 2023-10-19
*/
public interface ActTaskMapper extends BaseMapperPlus<TaskVo, TaskVo> {
/**
* 获取待办信息
*
* @param page 分页
* @param queryWrapper 条件
* @param userId 用户id
* @param groupIds 用户角色id
* @return 结果
*/
Page<TaskVo> getTaskWaitByPage(@Param("page") Page<TaskVo> page, @Param(Constants.WRAPPER) Wrapper<TaskVo> queryWrapper, @Param("userId") String userId, @Param("groupIds") List<String> groupIds);
}

View File

@ -31,11 +31,9 @@ public class ActHiProcinstServiceImpl implements IActHiProcinstService {
*/ */
@Override @Override
public List<ActHiProcinst> selectByBusinessKeyIn(List<String> businessKeys) { public List<ActHiProcinst> selectByBusinessKeyIn(List<String> businessKeys) {
return TenantHelper.ignore(() -> return baseMapper.selectList(new LambdaQueryWrapper<ActHiProcinst>()
baseMapper.selectList(new LambdaQueryWrapper<ActHiProcinst>()
.in(ActHiProcinst::getBusinessKey, businessKeys) .in(ActHiProcinst::getBusinessKey, businessKeys)
.eq(ActHiProcinst::getTenantId, TenantHelper.getTenantId())) .eq(ActHiProcinst::getTenantId, TenantHelper.getTenantId()));
);
} }
/** /**
@ -45,10 +43,9 @@ public class ActHiProcinstServiceImpl implements IActHiProcinstService {
*/ */
@Override @Override
public ActHiProcinst selectByBusinessKey(String businessKey) { public ActHiProcinst selectByBusinessKey(String businessKey) {
return TenantHelper.ignore(() -> return baseMapper.selectOne(new LambdaQueryWrapper<ActHiProcinst>()
baseMapper.selectOne(new LambdaQueryWrapper<ActHiProcinst>()
.eq(ActHiProcinst::getBusinessKey, businessKey) .eq(ActHiProcinst::getBusinessKey, businessKey)
.eq(ActHiProcinst::getTenantId, TenantHelper.getTenantId())) .eq(ActHiProcinst::getTenantId, TenantHelper.getTenantId()));
);
} }
} }

View File

@ -5,14 +5,11 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.dto.RoleDTO;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.common.tenant.helper.TenantHelper;
@ -23,7 +20,6 @@ import org.dromara.workflow.domain.bo.*;
import org.dromara.workflow.domain.vo.MultiInstanceVo; import org.dromara.workflow.domain.vo.MultiInstanceVo;
import org.dromara.workflow.domain.vo.TaskVo; import org.dromara.workflow.domain.vo.TaskVo;
import org.dromara.workflow.flowable.cmd.*; import org.dromara.workflow.flowable.cmd.*;
import org.dromara.workflow.mapper.ActTaskMapper;
import org.dromara.workflow.service.IActTaskService; import org.dromara.workflow.service.IActTaskService;
import org.dromara.workflow.utils.WorkflowUtils; import org.dromara.workflow.utils.WorkflowUtils;
import org.flowable.common.engine.impl.identity.Authentication; import org.flowable.common.engine.impl.identity.Authentication;
@ -38,6 +34,7 @@ import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance; import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery; import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.task.service.impl.persistence.entity.TaskEntity; import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -61,7 +58,6 @@ public class ActTaskServiceImpl implements IActTaskService {
private final HistoryService historyService; private final HistoryService historyService;
private final IdentityService identityService; private final IdentityService identityService;
private final ManagementService managementService; private final ManagementService managementService;
private final ActTaskMapper actTaskMapper;
/** /**
* 启动任务 * 启动任务
@ -142,6 +138,7 @@ public class ActTaskServiceImpl implements IActTaskService {
if (task.isSuspended()) { if (task.isSuspended()) {
throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
} }
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
//办理委托任务 //办理委托任务
if (ObjectUtil.isNotEmpty(task.getDelegationState()) && FlowConstant.PENDING.equals(task.getDelegationState().name())) { if (ObjectUtil.isNotEmpty(task.getDelegationState()) && FlowConstant.PENDING.equals(task.getDelegationState().name())) {
taskService.resolveTask(completeTaskBo.getTaskId()); taskService.resolveTask(completeTaskBo.getTaskId());
@ -159,6 +156,8 @@ public class ActTaskServiceImpl implements IActTaskService {
if (CollUtil.isEmpty(list)) { if (CollUtil.isEmpty(list)) {
UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus()); UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus());
managementService.executeCommand(updateBusinessStatusCmd); managementService.executeCommand(updateBusinessStatusCmd);
} else {
sendMessage(list, processInstance.getName(), completeTaskBo.getMessageType(),null);
} }
return true; return true;
} catch (Exception e) { } catch (Exception e) {
@ -166,6 +165,19 @@ public class ActTaskServiceImpl implements IActTaskService {
} }
} }
/**
* 发送消息
*
* @param list 任务
* @param name 流程名称
* @param messageType 消息类型
* @param message 消息内容为空则发送默认配置的消息内容
*/
@Async
public void sendMessage(List<Task> list, String name, List<String> messageType,String message) {
WorkflowUtils.sendMessage(list, name, messageType,message);
}
/** /**
* 查询当前用户的待办任务 * 查询当前用户的待办任务
* *
@ -173,33 +185,47 @@ public class ActTaskServiceImpl implements IActTaskService {
*/ */
@Override @Override
public TableDataInfo<TaskVo> getTaskWaitByPage(TaskBo taskBo) { public TableDataInfo<TaskVo> getTaskWaitByPage(TaskBo taskBo) {
PageQuery pageQuery = new PageQuery();
pageQuery.setPageNum(taskBo.getPageNum());
pageQuery.setPageSize(taskBo.getPageSize());
QueryWrapper<TaskVo> queryWrapper = new QueryWrapper<>();
List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles(); List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
String userId = String.valueOf(LoginHelper.getUserId()); String userId = String.valueOf(LoginHelper.getUserId());
queryWrapper.eq("t.business_status_", BusinessStatusEnum.WAITING.getStatus()); TaskQuery query = taskService.createTaskQuery();
queryWrapper.eq("t.tenant_id_", TenantHelper.getTenantId()); query.taskTenantId(TenantHelper.getTenantId()).taskCandidateOrAssigned(userId);
if (CollUtil.isNotEmpty(roles)) {
List<String> groupIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId()));
query.taskCandidateGroupIn(groupIds);
}
if (StringUtils.isNotBlank(taskBo.getName())) { if (StringUtils.isNotBlank(taskBo.getName())) {
queryWrapper.like("t.name_", taskBo.getName()); query.taskNameLike("%" + taskBo.getName() + "%");
} }
if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) { if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) {
queryWrapper.like("t.processDefinitionName", taskBo.getProcessDefinitionName()); query.processDefinitionNameLike("%" + taskBo.getProcessDefinitionName() + "%");
} }
if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) { if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) {
queryWrapper.eq("t.processDefinitionKey", taskBo.getProcessDefinitionKey()); query.processDefinitionKey(taskBo.getProcessDefinitionKey());
} }
Page<TaskVo> page = TenantHelper.ignore(() -> List<Task> taskList = query.listPage(taskBo.getPageNum(), taskBo.getPageSize());
actTaskMapper.getTaskWaitByPage(pageQuery.build(), queryWrapper, userId, StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId()))) List<ProcessInstance> processInstanceList = null;
); if (CollUtil.isNotEmpty(taskList)) {
List<TaskVo> taskList = page.getRecords(); Set<String> processInstanceIds = StreamUtils.toSet(taskList, Task::getProcessInstanceId);
for (TaskVo task : taskList) { processInstanceList = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIds).list();
task.setBusinessStatusName(BusinessStatusEnum.getEumByStatus(task.getBusinessStatus()));
task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId()));
task.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
} }
return new TableDataInfo<>(taskList, page.getTotal()); List<TaskVo> list = new ArrayList<>();
for (Task task : taskList) {
TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class);
if (CollUtil.isNotEmpty(processInstanceList)) {
processInstanceList.stream().filter(e -> e.getId().equals(task.getProcessInstanceId())).findFirst().ifPresent(e -> {
taskVo.setBusinessStatus(e.getBusinessStatus());
taskVo.setBusinessStatusName(BusinessStatusEnum.getEumByStatus(taskVo.getBusinessStatus()));
taskVo.setProcessDefinitionKey(e.getProcessDefinitionKey());
taskVo.setProcessDefinitionName(e.getProcessDefinitionName());
});
}
taskVo.setAssignee(StringUtils.isNotBlank(task.getAssignee()) ? Long.valueOf(task.getAssignee()) : null);
taskVo.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId()));
taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
list.add(taskVo);
}
long count = query.count();
return new TableDataInfo<>(list, count);
} }
/** /**
@ -569,6 +595,9 @@ public class ActTaskServiceImpl implements IActTaskService {
for (Task t : list) { for (Task t : list) {
taskService.setAssignee(t.getId(), historicTaskInstance.getAssignee()); taskService.setAssignee(t.getId(), historicTaskInstance.getAssignee());
} }
//发送消息
String message = "您的【" + processInstance.getName() + "】单据已经被驳回,请您注意查收。";
sendMessage(list, processInstance.getName(), backProcessBo.getMessageType(),message);
//删除流程实例垃圾数据 //删除流程实例垃圾数据
for (ExecutionEntity executionEntity : executionEntities) { for (ExecutionEntity executionEntity : executionEntities) {
DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId()); DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId());

View File

@ -11,11 +11,15 @@ import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.reflect.ReflectUtils; import org.dromara.common.core.utils.reflect.ReflectUtils;
import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mail.utils.MailUtils;
import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.system.domain.SysUserRole; import org.dromara.system.domain.SysUserRole;
import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.workflow.common.constant.FlowConstant; import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.workflow.common.enums.BusinessStatusEnum; import org.dromara.workflow.common.enums.BusinessStatusEnum;
import org.dromara.workflow.common.enums.MessageTypeEnum;
import org.dromara.workflow.domain.ActHiProcinst; import org.dromara.workflow.domain.ActHiProcinst;
import org.dromara.workflow.domain.vo.MultiInstanceVo; import org.dromara.workflow.domain.vo.MultiInstanceVo;
import org.dromara.workflow.domain.vo.ParticipantVo; import org.dromara.workflow.domain.vo.ParticipantVo;
@ -36,7 +40,6 @@ import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.task.api.Task; import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance; import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.persistence.entity.TaskEntity; import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamReader;
@ -334,4 +337,45 @@ public class WorkflowUtils {
} }
} }
} }
/**
* 发送消息
*
* @param list 任务
* @param name 流程名称
* @param messageType 消息类型
* @param message 消息内容为空则发送默认配置的消息内容
*/
public static void sendMessage(List<Task> list, String name, List<String> messageType,String message) {
Set<Long> userIds = new HashSet<>();
if(StringUtils.isBlank(message)){
message = "有新的【" + name + "】单据已经提交至您的待办,请及时处理。";
}
for (Task t : list) {
ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId());
if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) {
List<SysUserRole> sysUserRoles = I_WORK_FLOW_USER_SERVICE.getUserRoleListByRoleIds(taskParticipant.getGroupIds());
if (CollUtil.isNotEmpty(sysUserRoles)) {
userIds.addAll(StreamUtils.toList(sysUserRoles, SysUserRole::getUserId));
}
}
List<Long> candidate = taskParticipant.getCandidate();
if (CollUtil.isNotEmpty(candidate)) {
userIds.addAll(candidate);
}
}
if (CollUtil.isNotEmpty(userIds)) {
List<SysUserVo> sysUserVoList = I_WORK_FLOW_USER_SERVICE.getUserListByIds(new ArrayList<>(userIds));
if (messageType.contains(MessageTypeEnum.SYSTEM_MESSAGE.getCode())) {
WebSocketMessageDto dto = new WebSocketMessageDto();
dto.setSessionKeys(new ArrayList<>(userIds));
dto.setMessage(message);
WebSocketUtils.publishMessage(dto);
} else if (messageType.contains(MessageTypeEnum.EMAIL_MESSAGE.getCode())) {
MailUtils.sendText(StreamUtils.join(sysUserVoList, SysUserVo::getEmail), "单据审批提醒", message);
} else if (messageType.contains(MessageTypeEnum.SMS_MESSAGE.getCode())) {
//todo 短信发送
}
}
}
} }

View File

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.workflow.mapper.ActTaskMapper">
<resultMap type="org.dromara.workflow.domain.vo.TaskVo" id="TaskWaitingVoResult">
<result property="id" column="ID_"/>
<result property="name" column="NAME_"/>
<result property="description" column="DESCRIPTION_"/>
<result property="priority" column="PRIORITY_"/>
<result property="owner" column="OWNER_"/>
<result property="assignee" column="ASSIGNEE_"/>
<result property="processInstanceId" column="PROC_INST_ID_"/>
<result property="executionId" column="EXECUTION_ID_"/>
<result property="taskDefinitionId" column="TASK_DEF_ID_"/>
<result property="processDefinitionId" column="PROC_DEF_ID_"/>
<result property="createTime" column="CREATE_TIME_"/>
<result property="endTime" column="END_TIME_"/>
<result property="taskDefinitionKey" column="TASK_DEF_KEY_"/>
<result property="dueDate" column="DUE_DATE_"/>
<result property="processDefinitionKey" column="key_"/>
<result property="category" column="CATEGORY_"/>
<result property="parentTaskId" column="PARENT_TASK_ID_"/>
<result property="tenantId" column="TENANT_ID_"/>
<result property="claimTime" column="CLAIM_TIME"/>
<result property="businessStatus" column="BUSINESS_STATUS_"/>
<result property="processDefinitionName" column="processDefinitionName"/>
<result property="processDefinitionKey" column="processDefinitionName"/>
</resultMap>
<select id="getTaskWaitByPage" resultMap="TaskWaitingVoResult">
select * from (SELECT
RES.*,AHP.business_status_ ,ARP.name_ as processDefinitionName,ARP.key_ as processDefinitionKey
FROM
ACT_RU_TASK RES
inner join ACT_HI_PROCINST AHP ON RES.PROC_INST_ID_ = AHP.PROC_INST_ID_
inner join ACT_RE_PROCDEF ARP ON ARP.ID_ = RES.PROC_DEF_ID_
WHERE (
RES.ASSIGNEE_ = #{userId}
OR (
RES.ASSIGNEE_ IS NULL
AND EXISTS (
SELECT
LINK.ID_
FROM
ACT_RU_IDENTITYLINK LINK
WHERE
LINK.TASK_ID_ = RES.ID_
AND LINK.TYPE_ = 'candidate'
AND (
LINK.USER_ID_ = #{userId}
<if test="groupIds != null and groupIds.size() > 0">
OR (
LINK.GROUP_ID_ IN
<foreach collection="groupIds" item="groupId" index="index" open="(" close=")" separator=",">
#{groupId}
</foreach>
)
</if>
)
)
)
)
ORDER BY
RES.CREATE_TIME_ DESC) t
${ew.getCustomSqlSegment}
</select>
</mapper>