应用开发平台集成工作流系列之13——工作流辅助功能设计与实现

背景

Camunda只是工作流引擎,并不是一套完整的工作流产品。尽管自带了一套管理界面,可以从web登录后进行流程建模和流程管理,但界面太粗糙,不可能用于生产环境的。
因此需要基于Camunda的API,通过集成和定制的方式,来实现工作流辅助功能。

这里的辅助功能,主要是指以下几项:

  • 我的待办
  • 我的已办
  • 我的申请

下面来具体展开说说。

我的待办

我的待办是用户待他处理的任务列表,可进行任务查看与办理。
image.png
常用的技术实现方式有两种,一是直接使用官方API中的方法,适合比较简单的场景;二是使用官方API中提供的native查询,通过sql语句来处理多表关联问题。

native查询方式虽然可以通过编写sql语句来处理多表关联问题,但是……查询结果仍然要映射到预设的对象中,以待办任务查询为例,查询结果对应Task接口,可以获取到任务名称(环节名称)、处理人账号、任务归属人,这些是可以用的,但是需要给用户显示流程类型名称、业务单据号,只能通过Task接口对应的标识、流程定义标识、流程实例标识来再进行一次甚至多次查询。这就尴尬了……这种native查询方式,适合过滤数据,即关联多表,把过滤条件传进去,但无法解决查询结果来源于多表的问题。

这时候就需要使用基于Mybatis的CustomSql方式来查询了,自定义mapper来实现。

实际执行过程中,发现Camunda根本就没有activiti中ManagementService下的executeCustomSQL方法,囧……

最后完全基于Mybatis了,自己写mapper.xml、mapper接口、service层,即读取activiti工作流引擎的库表,关联查询,返回数据,映射到自定义的对象上,实际开发通过,开发工作量比直接使用官方API要大一点,但想取数据可以直接通过关联表的方式直接取到,不用受官方api的条条框框约束,先把主表对象取回来,再去其他表里取数据,多次查询。这样要方便很多,性能上也大大提升。

<?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="tech.abc.platform.workflow.mapper.ProcessTaskMapper">

    <!-- 公用查询-->
    <sql id="query">select * from (
        select t1.ID_ AS id, #任务标识
        t1.NAME_ as node_name, #环节名称
        t1.CREATE_TIME_ as create_time, #任务创建时间
        t1.ASSIGNEE_ as assignee,  #处理人
        t5.name as assignee_name,  #处理人姓名
        t1.TASK_DEF_KEY_ as task_definition_key, #任务定义标识
        t1.OWNER_ as owner, #任务拥有者
        t1.PROC_INST_ID_ AS process_instance_id, #流程实例标识
        t3.PROC_DEF_ID_ as process_definition_id, #流程定义标识
        t2.NAME_ as process_definition_name, #流程名称
        t3.PROC_DEF_KEY_ as process_definition_key, #流程编码
        t3.START_USER_ID_ as process_apply_id, #申请人id
        t4.name as process_apply_name, #申请人姓名
        t3.BUSINESS_KEY_ as business_no, #单号
        t1.DELEGATION_ as delegation, #委派状态
        t1.EXECUTION_ID_ as  execution_id #执行流标识
        from act_ru_task t1
        LEFT JOIN act_re_procdef t2
        on t1.PROC_DEF_ID_=t2.id_
        LEFT JOIN act_hi_procinst t3
        on t1.PROC_INST_ID_=t3.PROC_INST_ID_
        LEFT JOIN sys_user t4
        on t3.START_USER_ID_=t4.id
        LEFT JOIN sys_user t5
        on t1.ASSIGNEE_=t5.id
        ) t
        ${ew.customSqlSegment}
    </sql>



    <!-- 流程任务 结果映射 -->
    <resultMap id="resultMap" type="tech.abc.platform.workflow.entity.ProcessTask">
        <id property="id" column="id"/>
        <result property="nodeName" column="node_name"/>
        <result property="createTime" column="create_time"/>
        <result property="assignee" column="assignee"/>
        <result property="assigneeName" column="assignee_name"/>
        <result property="taskDefinitionKey" column="task_definition_key"/>
        <result property="owner" column="owner"/>
        <result property="processInstanceId" column="process_instance_id"/>
        <result property="processDefinitionId" column="process_definition_id"/>
        <result property="processDefinitionName" column="process_definition_name"/>
        <result property="processDefinitionKey" column="process_definition_key"/>
        <result property="processApplyId" column="process_apply_id"/>
        <result property="processApplyName" column="process_apply_name"/>
        <result property="businessNo" column="business_no"/>
        <result property="delegation" column="delegation"/>
        <result property="executionId" column="execution_id"/>
    </resultMap>
    <!-- 待办任务查询-->
    <sql id="toTodoTaskQuery">select * from (
        select t1.ID_ AS id, #任务标识
        t1.NAME_ as node_name, #环节名称
        t1.CREATE_TIME_ as create_time, #任务创建时间
        t1.ASSIGNEE_ as assignee,  #处理人
        t5.name as assignee_name,  #处理人姓名
        t1.TASK_DEF_KEY_ as task_definition_key, #任务定义标识
        t1.OWNER_ as owner, #任务拥有者
        t1.PROC_INST_ID_ AS process_instance_id, #流程实例标识
        t3.PROC_DEF_ID_ as process_definition_id, #流程定义标识
        t2.NAME_ as process_definition_name, #流程名称
        t3.PROC_DEF_KEY_ as process_definition_key, #流程编码
        t3.START_USER_ID_ as process_apply_id, #申请人id
        t4.name as process_apply_name, #申请人姓名
        t3.BUSINESS_KEY_ as business_no, #单号
        t1.DELEGATION_ as delegation, #委派状态
        t8.user_id as candidate_user, # 候选人
        t1.EXECUTION_ID_ as  execution_id #执行流标识
        from act_ru_task t1
        LEFT JOIN act_re_procdef t2
        on t1.PROC_DEF_ID_=t2.id_
        LEFT JOIN act_hi_procinst t3
        on t1.PROC_INST_ID_=t3.PROC_INST_ID_
        LEFT JOIN sys_user t4
        on t3.START_USER_ID_=t4.id
        LEFT JOIN sys_user t5
        on t1.ASSIGNEE_=t5.id
        LEFT JOIN act_ru_identitylink t6
        on t1.ID_=t6.TASK_ID_
        LEFT JOIN sys_user_group t7
        on t7.ID=t6.GROUP_ID_
        LEFT JOIN sys_group_user t8
        on t8.group_id=t7.id
        ) t
        ${ew.customSqlSegment}
    </sql>



    <!-- 待办任务 结果映射 -->
    <resultMap id="toTodoTaskResultMap" type="tech.abc.platform.workflow.entity.ProcessTask">
        <id property="id" column="id"/>
        <result property="nodeName" column="node_name"/>
        <result property="createTime" column="create_time"/>
        <result property="assignee" column="assignee"/>
        <result property="assigneeName" column="assignee_name"/>
        <result property="taskDefinitionKey" column="task_definition_key"/>
        <result property="owner" column="owner"/>
        <result property="processInstanceId" column="process_instance_id"/>
        <result property="processDefinitionId" column="process_definition_id"/>
        <result property="processDefinitionName" column="process_definition_name"/>
        <result property="processDefinitionKey" column="process_definition_key"/>
        <result property="processApplyId" column="process_apply_id"/>
        <result property="processApplyName" column="process_apply_name"/>
        <result property="businessNo" column="business_no"/>
        <result property="delegation" column="delegation"/>
        <result property="candidateUser" column="candidate_user"/>
        <result property="executionId" column="execution_id"/>
    </resultMap>

    <!-- 分页查询 -->
    <select id="customPage"  resultMap="resultMap">
        <include refid="query"></include>
    </select>

    <!-- 单条查询 -->
    <select id="get"  resultMap="resultMap">
        <include refid="query"></include>
    </select>


    <!-- 待办任务查询 -->
    <select id="todoTask"  resultMap="toTodoTaskResultMap">
        <include refid="toTodoTaskQuery"></include>
    </select>

</mapper>

我的申请

我的申请是用户方便快捷查看自己发起的流程列表,关注尚未结束流程的当前进度,如当前环节、当前处理人等,以及已经结束的流程,历史单据信息和审批信息。
image.png
一种设计方案,是将这部分单据按照是否结束拆分成两个菜单,称为我的申请和结束单据。这种方案,对于用户来说并不太友好,比如,一些临近结束或已经结束的流程,用户并不清楚处理进度,可能需要去两个菜单里都找一下。因此,还是采用1个菜单,用户在这个菜单下可以找到所有数据,更人性化一些。

基于上面的功能设计,官方的api返回的字段信息太有限了,还得通过类似查询我的待办的实现方式,自定义sql关联表来实现。

<?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="tech.abc.platform.workflow.mapper.ProcessInstanceMapper">

    <!-- 公用查询-->
    <sql id="query">  select * from (
        select t1.PROC_INST_ID_ AS id, #流程实例标识
        t1.BUSINESS_KEY_ as business_no, #单号
        t1.PROC_DEF_ID_ as process_definition_id, #流程定义标识
        t1.PROC_DEF_KEY_ as process_definition_key, #流程编码
        t2.NAME_ as process_definition_name, #流程名称
        t1.START_TIME_ as start_time, #启动时间
        t1.END_TIME_ as end_time, #结束时间
        t1.STATE_ as state, #状态
        t1.START_USER_ID_ as process_apply_id, #申请人id
        t4.NAME as process_apply_name, #申请人姓名
        t3.NAME_ as node_name, #环节名称
        t3.ASSIGNEE_ as node_assignee,  #环节处理人
        t5.NAME as node_assignee_name #环节处理人姓名
        from act_hi_procinst t1
        LEFT JOIN act_re_procdef t2
        on t1.PROC_DEF_ID_=t2.id_
        LEFT JOIN act_ru_task t3
        on t1.PROC_INST_ID_=t3.PROC_INST_ID_
        LEFT JOIN sys_user t4
        on t1.START_USER_ID_=t4.id
        LEFT JOIN sys_user t5
        on t3.ASSIGNEE_=t5.id
        ) t
        ${ew.customSqlSegment}</sql>


    <!-- 流程实例 结果映射 -->
    <resultMap id="resultMap" type="tech.abc.platform.workflow.entity.ProcessInstance">
        <id property="id" column="id"/>
        <result property="businessNo" column="business_no"/>
        <result property="processDefinitionId" column="process_definition_id"/>
        <result property="processDefinitionKey" column="process_definition_key"/>
        <result property="processDefinitionName" column="process_definition_name"/>
        <result property="startTime" column="start_time"/>
        <result property="endTime" column="end_time"/>
        <result property="state" column="state"/>
        <result property="processApplyId" column="process_apply_id"/>
        <result property="processApplyName" column="process_apply_name"/>
        <result property="nodeName" column="node_name"/>
        <result property="nodeAssignee" column="node_assignee"/>
        <result property="nodeAssigneeName" column="node_assignee_name"/>


    </resultMap>

    <!-- 分页查询 -->
    <select id="customPage"  resultMap="resultMap">
        <include refid="query"></include>
    </select>

    <!-- 单条查询 -->
    <select id="get"  resultMap="resultMap">
        <include refid="query"></include>
    </select>

</mapper>

我的已办

我的已办是查询当前人员处理过的所有流程
image.png
实现参照我的待办和我的申请,通过自定义sql方式实现。因activiti审批意见功能不完善,通过自定义表实现了,但该表同样没有保存任务标识(保存了也没用,对于委托、转办等功能,activiti共用同一条任务,任务标识是同一个),因此,在我的已办列表中无法显示当时的审批意见(实际也并不需要),点击详情后加载审批历史可以看到。

同时,如一个人在某条审批流程中多个环节或同一环节多次处理(如回退引发),在我的已办中会显示多条,不会也不应该按流程合并。

<?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="tech.abc.platform.workflow.mapper.ProcessHistoricTaskMapper">

    <!-- 公用查询-->
    <sql id="query">
        select * from (
        select t1.ID_ AS id, #任务标识
        t1.NAME_ as node_name, #环节名称
        t1.START_TIME_ as start_time, #任务开始时间
        t1.END_TIME_ as end_time, #任务结束时间
        t1.DELETE_REASON_ as delete_reason, #任务移除原因
        t1.ASSIGNEE_ as assignee,  #处理人
        t5.name as assignee_name,  #处理人姓名
        t1.TASK_DEF_KEY_ as task_definition_key, #任务定义标识
        t1.OWNER_ as owner, #任务拥有者
        t1.PROC_INST_ID_ AS process_instance_id, #流程实例标识
        t3.PROC_DEF_ID_ as process_definition_id, #流程定义标识
        t2.NAME_ as process_definition_name, #流程名称
        t3.PROC_DEF_KEY_ as process_definition_key, #流程编码
        t3.START_USER_ID_ as process_apply_id, #申请人id
        t4.name as process_apply_name, #申请人姓名
        t3.BUSINESS_KEY_ as business_no #单号
        from act_hi_taskinst t1
        LEFT JOIN act_re_procdef t2
        on t1.PROC_DEF_ID_=t2.id_
        LEFT JOIN act_hi_procinst t3
        on t1.PROC_INST_ID_=t3.PROC_INST_ID_
        LEFT JOIN sys_user t4
        on t3.START_USER_ID_=t4.id
        LEFT JOIN sys_user t5
        on t1.ASSIGNEE_=t5.id
        ) t
        ${ew.customSqlSegment}
    </sql>


    <!-- 流程任务 结果映射 -->
    <resultMap id="resultMap" type="tech.abc.platform.workflow.entity.ProcessHistoricTask">
        <id property="id" column="id"/>
        <result property="nodeName" column="node_name"/>
        <result property="startTime" column="start_time"/>
        <result property="endTime" column="end_time"/>
        <result property="deleteReason" column="delete_reason"/>
        <result property="assignee" column="assignee"/>
        <result property="assigneeName" column="assignee_name"/>
        <result property="taskDefinitionKey" column="task_definition_key"/>
        <result property="owner" column="owner"/>
        <result property="processInstanceId" column="process_instance_id"/>
        <result property="processDefinitionId" column="process_definition_id"/>
        <result property="processDefinitionName" column="process_definition_name"/>
        <result property="processDefinitionKey" column="process_definition_key"/>
        <result property="processApplyId" column="process_apply_id"/>
        <result property="processApplyName" column="process_apply_name"/>
        <result property="businessNo" column="business_no"/>
    </resultMap>

    <!-- 分页查询 -->
    <select id="customPage"  resultMap="resultMap">
        <include refid="query"></include>
    </select>

    <!-- 单条查询 -->
    <select id="get"  resultMap="resultMap">
        <include refid="query"></include>
    </select>


</mapper>

开发平台资料

平台名称:一二三开发平台
简介: 企业级通用开发平台
设计资料:csdn专栏
开源地址:Gitee
开源协议:MIT
开源不易,欢迎收藏、点赞、评论。

猜你喜欢

转载自blog.csdn.net/seawaving/article/details/132322073