请假工作流工作总结

  • Post author:
  • Post category:其他


这篇文章是请假工作流中遇到的坑和对这一阶段的工作的总结。
先对工作流进行简单的说明,工作流是OA中常用的专业名词,通常用在请假,报销等需要多级领导的审核,执行的规范化,java中常用的工作流组件有jbpm,activiti,在此项目中,我们选用activiti.activiti有23张表,但是重要的表有下面几张。
  • act_ge_bytearray二进制表,用于存放bpmn和png图片,如果要查询文件,须知道部署Id(deploymentId)。
  • act_re_deployment:部署表,要使用一个流程图时第一步就是部署流程图。该表的重要字段有:id_:pdid:pdkey:pdversion:随机数,name:名称,key:名称,version:版本号。如果名称不变,每次部署,版本号加1,如果名称改变,则版本号从1开始计算
  • act_hi_act:流程图中正在执行或者已经执行完的节点。重要字段有:pro_def_id:流程定义的id(pdid),没有单独的流程实例表,如果没有分支,流程实例Id和执行Id相同,如果有分支,则不同,proc_inst_id:流程实例Id,execution_id:执行Id
  • act_hi_procinst:历史的流程定义实例,正在执行的任务也在其中。如果end_time为null说明正在执行
  • act_ru_execution:代表正在执行的流程实例表

    如果当期正在执行的流程实例结束以后,该行在这张表中就被删除掉了,所以该表也是一个临时表,重要字段有:proc_inst_id:piid流程实例id,在不存在并发的情况下流程实例id和流程执行id相同,act_id:当前正在执行的流程实例的正在执行的节点
  • act_ru_task:正在执行的任务表,临时表,重要字段有:id_:主键,任务Id,execution_id:执行Id,根据该id查询出来的任务肯定是一个,proc_inst_id:piid:如果没有并发,则是一个,如果有并发,则是多个,name_:任务的名称,assignee:任务的执行人。
介绍完表以后,我来描述下一套工作流执行下来的几大步骤,
  • 第一步:画图,画图是很重要的准备工作,我们需要根据业务需求画流程图。
  • 第二步:部署流程图。
  • 第三步:开启一个流程实例,例如请假,一个人提交了一个请假申请,即开启了一个请假流程实例。
  • 第四步:执行任务,任务的接收人可以在图中定义,也可以在程序中执行,流程图进行到那一步,该接收人就要执行任务,根据执行的条件,程序自动选择下一步的路线。当一个流程走到最后一步,结束task的时候,一个流程就算是运行完毕。好的,下面我会对每一步进行图文说明。
画图

这里写图片描述

这是这次请假的流程图,先说明下此次请假老师给的需求,需求如下
  • 四类人,教学人员,教学人员兼班主任,行政人员,教学人员兼班主任。

    这里写图片描述
主要有两个条件,人员类型,请假天数。
图的几处细节:

这里写图片描述

  • 定义每处节点时,该节点的id即该审核老师的英文,例:teachingLeader

这里写图片描述

  • 节点的候选人定义为变量,为了好区分,也定义为该老师的英文,例:#{teachingLeaders}

    这里写图片描述

  • 该箭头条件:${staffType==1 || staffType == 3 || staffType == 4 }教职工类型为1或3或4

    这里写图片描述

  • 该箭头条件为:${!teachingDirectorPass},教学处主任老师未通过

    这里写图片描述

  • 该箭头条件为:${leaveTime <= 1 && staffType =3},天数<=1并且职工类型为3

    图画好了,接下来就是写程序了。

准备工作

这里写图片描述

  • 引入jar包,ant工程,所有我们先把jar包放入BODL-DIST工程中,新建了一个文件夹activiti5. 22,我们使用5.22版本的activiti
  • 我们需要在SRV项目中的res根目录中添加activiti的配置文件activiti.cfg.xml(注:文件名不能写错,位置也不能错,默认位置,默认文件名), processEngineConfiguration最重要,与数据库连接,



    private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    生成流程引擎,如果数据库中没有23张,第一次启动时,会自动生成23张表
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    <!-- 配置工作流的bean -->
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcDriver" value="org.postgresql.Driver"></property>
        <property name="jdbcUrl" value="jdbc:postgresql://192.168.0.115:5432/boas_oa"></property>
        <property name="jdbcUsername" value="postgres"></property>
        <property name="jdbcPassword" value="root123"></property>
        <!-- 创建表的策略  -->
        <property name="databaseSchemaUpdate" value="true"></property>
    </bean>
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
    </bean>

    <!-- 7大接口 -->
    <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
    <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
    <bean id="formService" factory-bean="processEngine" factory-method="getFormService"/>
    <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
    <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
    <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
    <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService"/>
</beans>
  • 生成leaveFlow表,表结构如下

    这里写图片描述
代码部分
  • 准备工作做好后,就该写代码了,结构如下
  • 部署,方法如下
    @Action(value = "deploy", results = { @Result(name = "deploy", type = "json", params = {"root", "jsonResult" }) })
    public String deploy() throws FileNotFoundException {
        //部署流程定义
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获得上传文件的输入流程
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("deployments/leave.zip");
        ZipInputStream zipInputStream = new ZipInputStream(in);
        //获取仓库服务,从类路径下部署
        Deployment deploy = processEngine.getRepositoryService().createDeployment().name("请假流程").addZipInputStream(zipInputStream).deploy();
        System.out.println(deploy.getName());
        return "deploy";
    }
  • 提交申请,页面如图,代码略

    这里写图片描述
后台代码:
    @Action(value = "start", results = { @Result(name = "leaveSubmit", type = "json", params = {"root", "jsonResult" }) })
    public String leaveSubmit() {
        SysUser sysUser = (SysUser) getSession().get(EBacsConstant.SESSION_LOGIN_USER.getTextValue());
        String startTime = getParameter("startTime");
        String endTime = getParameter("endTime");
        String reason = getParameter("reason");
        String leaveType = getParameter("leaveType");
        LeaveFlowInfo leave = new LeaveFlowInfo();
        try {
            //开始时间
            leave.setStartTime(sdf.parse(startTime));
            //结束时间
            leave.setEndTime(sdf.parse(endTime));
            //申请时间
            leave.setApplyTime(new Date(System.currentTimeMillis()));
        } catch (ParseException e) {
            log.error("日期转换失败:" + e.getMessage());
        }
        //请假类型
        leave.setLeaveType(leaveType);
        //请假原因
        leave.setReason(reason);
        leave.setUserUuid(sysUser.getUuid());
        leave.setUserName(sysUser.getRealName());
        boolean flag = false;
        try {

            StringBuilder message = new StringBuilder();
            Map<String, Object> variables = new HashMap<String, Object>();
            flag = setVariables(message, endTime, startTime,variables);
            if(flag) {
                workflowService.startWorkflow(leave, variables);
                jsonResult = QueryResult.create().success(flag).msgDesc("启动请假流程成功");
            } else {
                jsonResult = QueryResult.create().success(flag).msgDesc(message.toString());
                log.error("启动请假流程失败,失败原因:" + message.toString());
            }
        } catch (Exception e) {
            jsonResult = QueryResult.create().success(flag).msgDesc("启动请假流程失败");
            log.error("启动请假流程失败,失败原因:" + e.getMessage());
        } finally {
        }
        return "leaveSubmit"; }
在这一步,要做两件事
  • 1,添加一条请假记录
  • 2,启动一个请假流程,在启动请假流程之前,需要将变量设置进去,请假时间,职工类型,每个审核人员的uuid,具体如下:(注:教研组长和处室主任的uuid通过调用接口获得,在权限系统中设置每个部门的领导,该领导即教研组长或处室主任。其他审核人员都是单个人,可以从staff表中的officiate中获得,这些变量都是必须设置的,如果有一项未设置,则请假流程无法启动)
private boolean setVariables(StringBuilder message,String endTime,String startTime,Map<String, Object> variables) throws Exception{
        //设置staffType,请假天数
        //1:教学人员,2:行政人员,3:教学人员兼班主任,4:教学兼行政人员
        Map<String, Object> paramObj = new HashMap<String, Object>();
        paramObj.put("idNo", sysUser.getUserName());
        StaffVO staffVO = getOutInterfaceCommonService().queryStaffInfoByIdNo(paramObj);
        String staffType = staffVO.getStaffType();
        if(StringUtils.isBlank(staffType) || Integer.parseInt(staffType) == 0 ||  Integer.parseInt(staffType) == -99 ) {
            message.append("教职工类型未设置");
            return false;
        }
        variables.put("staffType", staffType);
        //设置请假天数
        long end = sdf.parse(endTime).getTime();
        long start = sdf.parse(startTime).getTime();

        float leaveTime = (float)(end - start)/ (1000 * 60 * 60 * 24);

        variables.put("leaveTime", leaveTime);

        //清空
        paramObj.clear();
        paramObj.put("userUuid", sysUser.getUuid());
        List<DepartmentInfo> dptList = getOutInterfaceCommonService().queryDepartmentCommander(paramObj);
        //设置教研组长和处室主任
        if(dptList != null && dptList.size() !=0) {
            if(dptList.size() == 1) {
                variables.put("teachingLeaders", dptList.get(0).getDptCommanderUuid()); //教研组长
                variables.put("officeLeader", dptList.get(0).getDptCommanderUuid()); //处室主任
            }else if(dptList.size() >= 2) {
                for(int i = 0;i < dptList.size(); i ++) {
                    if(dptList.get(i).getDptName().contains("组")) {
                        variables.put("teachingLeaders", dptList.get(0).getDptCommanderUuid()); //教研组长
                        dptList.remove(i);
                    }
                }
                variables.put("officeLeader", dptList.get(0).getDptCommanderUuid()); //处室主任
            }else {
                message.append(" 该职工未被分配处室或教研组长,或教研组长,处室主任未指定");
                return false;
            }
        }else {
            message.append(" 该职工未分配处室或教研组长,或教研组长,处室主任未指定");
            return false;
        }

        //教学处主任
        String teachingDirector = getStaffBuOfficiate("2");
        if(StringUtils.isNotBlank(teachingDirector)) {
            variables.put("teachingDirector", teachingDirector); 
        }else {
            message.append(" 教学处主任未指定");
            return false;
        }
        //学生处主任
        String studentDirector = getStaffBuOfficiate("37");
        if(StringUtils.isNotBlank(studentDirector)) {
            variables.put("studentDirector", studentDirector); 
        }else {
            message.append(" 学生处主任未指定");
            return false;
        }

        //教学副校长
        String teachingPresident = getStaffBuOfficiate("38");
        if(StringUtils.isNotBlank(teachingPresident)) {
            variables.put("teachingPresident", teachingPresident); 
        }else {
            message.append(" 教学副校长未指定");
            return false;
        }

        //德育副校长
        String educationPresident = getStaffBuOfficiate("39");
        if(StringUtils.isNotBlank(educationPresident)) {
            variables.put("educationPresident", educationPresident); 
        }else {
            message.append(" 德育副校长未指定");
            return false;
        }

        //行政副校长
        String executivePrecident = getStaffBuOfficiate("40");
        if(StringUtils.isNotBlank(executivePrecident)) {
            variables.put("executivePrecident", executivePrecident); 
        }else {
            message.append(" 行政副校长未指定");
            return false;
        }

        //行政副校长
        String president = getStaffBuOfficiate("3");
        if(StringUtils.isNotBlank(president)) {
            variables.put("president", president); 
        }else {
            message.append(" 校长未指定");
            return false;
        }

        variables.put("applyUser", sysUser.getUuid());

        return true;
    }
启动流程的代码如下
    public ProcessInstance startWorkflow(LeaveFlowInfo entity, Map<String, Object> variables)  throws Exception{
        getLeaveFlowDao().insert(entity);
        logger.debug("save entity: {}", entity);
        int businessKey = entity.getId();
        ProcessInstance processInstance = null;
        try {
            // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中   processEngine.getIdentityService().setAuthenticatedUserId(entity.getUserUuid());
            processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("leave", String.valueOf(businessKey), variables);

            String processInstanceId = processInstance.getId();
            entity.setProcessInstanceId(processInstanceId);
            //更新leaveInfo,添加processInstanceId
            getLeaveFlowDao().update(entity);
            logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"leave", businessKey, processInstanceId, variables});
        } finally {
            processEngine.getIdentityService().setAuthenticatedUserId(null);
        }
        return processInstance;
    }
请假审核
  • 流程实例启动以后,根据设置的条件,可以得到下一个审核人员,下面是任务列表后台代码
    @Action(value = "taskListPage", results = {@Result(name = "taskListPage", location = "/WEB-INF/pages/office$automatic/leaveflow/task_list.jsp")})
    public String taskList() {
        String userId = sysUser.getUuid();
        List<LeaveFlowInfo> leaveFlowInfos = new ArrayList<>();
        List<Task> taskList = processEngine.getTaskService().createTaskQuery().taskCandidateOrAssigned(userId).list();
        Map<String, Object> typeCode = new HashMap<String, Object>();
        try {
            if(taskList != null && taskList.size() != 0) {
                for (Task task : taskList) {
                    String processInstanceId = task.getProcessInstanceId();
                    ProcessInstance processInstance = processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
                    if (processInstance == null) {
                        continue;
                    }
                    String businessKey = processInstance.getBusinessKey();
                    if (businessKey == null) {
                        continue;
                    }
                        LeaveFlowInfo leaveInfo = workflowService.getLeaveById(Integer.parseInt(businessKey));
                        leaveInfo.setTask(task);
                        leaveInfo.setProcessInstance(processInstance);
                        leaveInfo.setProcessDefinition(workflowService.getProcessDefinition(processInstance.getProcessDefinitionId()));
                        leaveFlowInfos.add(leaveInfo);
                }
            }
            Map<String, Object> paramObj = new HashMap<String, Object>();
            paramObj.put("typeCode", "qjlb");
            //查询所有请假类别
            typeCode = getOutInterfaceCommonService().queryByDictTypeCode(paramObj);
        } catch (Exception e) {
            log.error("任务查询失败,失败原因:" + e.getMessage());
        }

        getRequest().setAttribute("result", leaveFlowInfos);
        getRequest().setAttribute("typeCode", typeCode);
        return "taskListPage";
    }
  • 前台代码
<div class="search">
     <div>
          <label>申请人姓名:</label>
          <input type="text"  id="leaveApplyName" placeholder="申请人姓名" style="width:180px;height:30px;"/>
          <label>审核状态:</label>
          <select id="leaveCheckStatus">
            <option value="-99" >全部</option>
            <c:forEach items="${qjshzt.result }" var="typeCodeMap">
                <c:if test="${typeCodeMap.dictKey == 0}">
                    <option selected value="${typeCodeMap.dictKey }" >${ typeCodeMap.dictName }</option>
                </c:if>
                <c:if test="${typeCodeMap.dictKey != 0}">
                    <option value="${typeCodeMap.dictKey }" >${ typeCodeMap.dictName }</option>
                </c:if>
            </c:forEach>
          </select>
     </div> 
     <input id="selectBtn" class="btn bg_blue"  type="button"  value="查询" />
  </div>

  <table  width="100%" border="0" cellspacing="0" cellpadding="0" class="table_1 mar_T10">
      <thead>
          <th class="fixed_width_4_id">序号</th>
          <th class="same_percent_width_of_2_6_column">假种</th>
          <th class="same_percent_width_of_2_6_column">申请人</th>
          <th class="same_percent_width_of_2_6_column">申请时间</th>
          <th class="same_percent_width_of_2_6_column">开始时间</th>
          <th class="same_percent_width_of_2_6_column">结束时间</th>
          <th class="same_percent_width_of_2_6_column">当前节点</th>
          <th class="same_percent_width_of_2_6_column">任务创建时间</th>
          <th class="same_percent_width_of_2_6_column">流程状态</th>
          <th class="same_percent_width_of_2_6_column">操作</th>
      </thead>
      <tbody id="queryLeaveInfoList">

        <c:forEach items="${result }" var="leave" varStatus="status" >
                <c:set var="task" value="${leave.task }" />
                <c:set var="pi" value="${leave.processInstance }" />
                <tr id="${leave.id }" tid="${task.id }">
                    <td>${status.count }</td>
                    <c:forEach items="${typeCode.result}" var="leaveTypeMap">
                        <c:if test="${leaveTypeMap.dictKey == leave.leaveType}">
                            <td>${leaveTypeMap.dictName }</td>     
                        </c:if>
                    </c:forEach>
                    <%-- <td>${leave.leaveType }</td> --%>
                    <td>${leave.userName }</td>
                    <td><fmt:formatDate value="${leave.applyTime }" pattern="yyyy-MM-dd HH:mm" /> </td>
                    <td><fmt:formatDate value="${leave.startTime }" pattern="yyyy-MM-dd HH:mm" /></td>
                    <td><fmt:formatDate value="${leave.endTime }" pattern="yyyy-MM-dd HH:mm" /></td>

                    <td>
                        <a class="trace" href='#' pid="${pi.id }" eid="${task.executionId}" pdid="${pi.processDefinitionId}" title="点击查看流程图"><font color="red">${task.name }</font></a>
                    </td>
                    <%--<td><a target="_blank" href='${ctx }/workflow/resource/process-instance?pid=${pi.id }&type=xml'>${task.name }</a></td> --%>
                    <td><fmt:formatDate value="${task.createTime }" pattern="yyyy-MM-dd HH:mm" /></td>
                    <td>${pi.suspended ? "已挂起" : "正常" };<b title='流程版本号'>V: ${leave.processDefinition.version }</b></td>
                    <td>
                        <c:if test="${empty task.assignee }">
                            <a class="claim" href="${ctx }/oa/leave/task/claim/${task.id}">签收</a>
                        </c:if>
                        <c:if test="${not empty task.assignee }">
                            <%-- 此处用tkey记录当前节点的名称 --%>
                            <a class="handle" tkey='${task.taskDefinitionKey }' tname='${task.name }' href="#">办理</a>
                        </c:if>
                    </td>
                </tr>
            </c:forEach>
      </tbody>
  </table>

  <!-- 下面是每个节点的模板,用来定义每个节点显示的内容 -->
    <!-- 使用DIV包裹,每个DIV的ID以节点名称命名,如果不同的流程版本需要使用同一个可以自己扩展(例如:在DIV添加属性,标记支持的版本) -->

    <!-- 教研组组长审批 -->
    <div id="teachingLeader" style="display: none">

        <!-- table用来显示信息,方便办理任务 -->
        <%@include file="view-form.jsp" %>
    </div>

    <!-- 教学处主任审批 -->
    <div id="teachingDirector" style="display: none">

        <!-- table用来显示信息,方便办理任务 -->
        <%@include file="view-form.jsp" %>
    </div>

    <!-- 处室主任 -->
    <div id="officeLeader" style="display: none">

        <!-- table用来显示信息,方便办理任务 -->
        <%@include file="view-form.jsp" %>
    </div>

    <!-- 学生处主任 -->
    <div id="studentDirector" style="display: none">

        <!-- table用来显示信息,方便办理任务 -->
        <%@include file="view-form.jsp" %>
    </div>

    <!-- 教学副校长 -->
    <div id="teachingPresident" style="display: none">

        <!-- table用来显示信息,方便办理任务 -->
        <%@include file="view-form.jsp" %>
    </div>

    <!-- 德育副校长 -->
    <div id="educationPresident" style="display: none">

        <!-- table用来显示信息,方便办理任务 -->
        <%@include file="view-form.jsp" %>
    </div>

    <!-- 行政副校长 -->
    <div id="executivePrecident" style="display: none">

        <!-- table用来显示信息,方便办理任务 -->
        <%@include file="view-form.jsp" %>
    </div>

    <!-- 校长 -->
    <div id="president" style="display: none">

        <!-- table用来显示信息,方便办理任务 -->
        <%@include file="view-form.jsp" %>
    </div>

    <!-- 申请调整 -->
    <div class="mar_LR10">
    <div id="modifyApply" style="display: none">
        <div class="info" style="display: none"></div>
        <div id="radio">
            <input type="radio" id="radio1" name="reApply" value="true" /><label for="radio1">调整申请</label>
            <input type="radio" id="radio2" name="reApply" checked="checked" value="false" /><label for="radio2">取消申请</label>
        </div>
        <hr />
        <table id="modifyApplyContent" style="display: none" class="s_add">
            <input type="hidden" id="leaveId" name="leaveId" />
            <tr>
                <td>请假类型:</td>
                <td>
                    <select id="leaveType" name="leaveType">
                        <c:forEach items="${typeCode.result }" var="leaveTypeMap">
                                <option value="${leaveTypeMap.dictKey }" >${leaveTypeMap.dictName }</option>
                            </c:forEach>
                    </select>
                </td>
            </tr>
            <tr>
                <td>开始时间:</td>
                <td><input type="text" id="startTime" name="startTime" /></td>
            </tr>
            <tr>
                <td>结束时间:</td>
                <td><input type="text" id="endTime" name="endTime" /></td>
            </tr>
            <tr>
                <td>请假原因:</td>
                <td>
                    <textarea id="reason" name="reason" style="width: 250px;height: 50px"></textarea>
                </td>
            </tr>
        </table>
        </div>
    </div>

    <!-- 销假 -->
    <div id="reportBack" style="display: none">
        <!-- table用来显示信息,方便办理任务 -->
        <%@include file="view-form.jsp" %>
        <hr/>
        <table>
            <tr>
                <td>实际请假开始时间:</td>
                <td>
                    <input id="realityStartTime" />
                </td>
            </tr>
            <tr>
                <td>实际请假开始时间:</td>
                <td>
                    <input id="realityEndTime" />
                </td>
            </tr>
        </table>
    </div>


代码分为几部分

:1,对获取的task数据遍历,2每个节点定义一个div,在点击办理的时候可以打开对应的div,其中申请调整的div和其他的div不同。

请假办理
  • 前台代码
function handle() {
    // 当前节点的英文名称
    var tkey = $(this).attr('tkey');
    // 当前节点的中文名称
    var tname = $(this).attr('tname');
    // 请假记录ID
    var rowId = $(this).parents('tr').attr('id');
    // 任务ID
    var taskId = $(this).parents('tr').attr('tid');
    // 使用对应的模板
    $('#' + tkey).data({
        taskId: taskId
    }).dialog({
        title: '流程办理[' + tname + ']',
        modal: true,
        width: handleOpts[tkey].width,
        height: handleOpts[tkey].height,
        open: function() {
            handleOpts[tkey].open.call(this, rowId, taskId);
        },
        buttons: handleOpts[tkey].btns
    });
}
//定义多个节点的处理页面,下面仅是教研组长,其他类似
var handleOpts = {
    //教研组长
    teachingLeader: {
        width: 300,
        height: 300,
        open: function(id) {
            // 打开对话框的时候读取请假内容
            loadDetail.call(this, id);
        },
        btns: [{
            text: '同意',
            click: function() {
                var taskId = $(this).data('taskId');

                // 设置流程变量
                complete(taskId, [{
                    key: 'teachingLeadersPass',
                    value: true,
                    type: 'B'
                }]);
            }
        }, {
            text: '驳回',
            click: function() {
                var taskId = $(this).data('taskId');

                $('<div/>', {
                    title: '填写驳回理由',
                    html: "<textarea id='teachingLeaderBackReason' style='width: 250px; height: 60px;'></textarea>"
                }).dialog({
                    modal: true,
                    buttons: [{
                        text: '驳回',
                        click: function() {
                            var teachingLeaderBackReason = $('#teachingLeaderBackReason').val();
                            if (teachingLeaderBackReason == '') {
                                alert('请输入驳回理由!');
                                return;
                            }

                            // 设置流程变量
                            complete(taskId, [{
                                key: 'teachingLeadersPass',
                                value: false,
                                type: 'B'
                            }, {
                                key: 'teachingLeaderBackReason',
                                value: teachingLeaderBackReason,
                                type: 'S'
                            }]);
                        }
                    }, {
                        text: '取消',
                        click: function() {
                            $(this).dialog('close');
                            $('#teachingLeader').dialog('close');
                        }
                    }]
                });
            }
        }, {
            text: '取消',
            click: function() {
                $(this).dialog('close');
            }
        }]
    }
  • 可以看到设置的变量有’teachingLeaderBackReason’,’teachingLeadersPass’等
  • 后台代码
 @Action(value = "complete", results = { @Result(name = "complete", type = "json", params = {"root", "jsonResult" }) })
    public String complete() {
        String taskId = getParameter("taskId");
        String keys = getParameter("keys");
        String values = getParameter("values");
        String types = getParameter("types");

        try {
            Variable variables = new Variable(keys, values, types);
            Map<String, Object> variableMap = variables.getVariableMap();
            if(variableMap.get("leaveId") != null) {
                workflowService.update(variableMap);
            }

            processEngine.getTaskService().complete(taskId, variableMap);
            jsonResult = QueryResult.create().success(true).msgDesc("办理成功");
        } catch (Exception e) {
            log.error("办理任务失败,失败原因:" + e.getMessage());
            jsonResult = QueryResult.create().success(false).msgDesc("办理失败");
        }

        return "complete";
    }
查询运行中的请假流程
@Action(value = "runningList", results = { @Result(name = "runningList", location = "/WEB-INF/pages/office$automatic/leaveflow/running_list.jsp") })
public String runningList() {
    Map<String, Object> typeCode = new HashMap<String, Object>();
    try {
        List<LeaveFlowInfo> list = workflowService.findRunningProcessInstaces();
        getRequest().setAttribute("leaveList", list);

        Map<String, Object> paramObj = new HashMap<String, Object>();
        paramObj.put("typeCode", "qjlb");
        //查询所有请假类别
        typeCode = getOutInterfaceCommonService().queryByDictTypeCode(paramObj);
        getRequest().setAttribute("typeCode", typeCode);
    } catch (Exception e) {
        log.error("查询运行中的流程实例失败:" + e.getMessage());
    }
    return "runningList";
}
#### 查询已结束的请假流程
@Action(value = "finishedList", results = { @Result(name = "finishedList", location = "/WEB-INF/pages/office$automatic/leaveflow/finished_list.jsp") })
public String finishedList() {
    Map<String, Object> typeCode = new HashMap<String, Object>();
    try {
        List<LeaveFlowInfo> list = workflowService.findFinishedProcessInstaces();
        getRequest().setAttribute("leaveList", list);
        Map<String, Object> paramObj = new HashMap<String, Object>();
        paramObj.put("typeCode", "qjlb");
        //查询所有请假类别
        typeCode = getOutInterfaceCommonService().queryByDictTypeCode(paramObj);
        getRequest().setAttribute("typeCode", typeCode);
    } catch (Exception e) {
        log.error("查询已结束的流程实例失败:" + e.getMessage());
    }
    return "finishedList";
}

···

注:此文借鉴咖啡兔的工作流项目,感谢!



版权声明:本文为fireaco原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。