前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >day59_BOS项目_11

day59_BOS项目_11

作者头像
黑泽君
发布2018-11-07 14:36:06
5790
发布2018-11-07 14:36:06
举报
文章被收录于专栏:黑泽君的专栏黑泽君的专栏
  • 今天内容安排:
    • 1、流程实例管理(查询流程实例、查看流程实例运行状态)
    • 2、将bos系统中的用户和角色同步到activiti框架的用户表和组表中去
    • 3、设计物流配送流程
    • 4、启动物流配送流程
    • 5、组任务操作(查询、拾取)
    • 6、个人任务操作(查询、办理)

1、流程实例管理

1.1、查询流程实例

第一步:创建一个流程实例管理ProcessInstanceAction,提供list()方法,查询流程实例列表数据

代码语言:javascript
复制
    // 注入Service
    @Autowired
    private RuntimeService runtimeService;

    /**
     * 查询流程实例(同步)
     * @return
     */
    public String list() {
        // 创建流程实例查询对象
        ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
        query.orderByProcessInstanceId().desc(); // 根据流程实例id排序,降序
        List<ProcessInstance> list = query.list(); // 执行查询,获得流程实例列表数据
        // 将流程实例列表数据压入值栈中
        ActionContext.getContext().getValueStack().set("list", list);
        return "list"; 
    }

第二步:配置struts.xml

代码语言:javascript
复制
    <!-- 流程实例管理:配置processInstanceAction-->
    <action name="processInstanceAction_*" class="processInstanceAction" method="{1}">
        <result name="list">/WEB-INF/pages/workflow/processinstance.jsp</result>
    </action>

第三步:提供processinstance.jsp页面,展示列表数据

代码语言:javascript
复制
<tbody>
    <s:iterator value="list">
        <tr>
            <td>${id}</td><!-- 流程实例id -->
            <td>${processDefinitionId}</td>
            <td>${activityId}</td><!-- 流程id(任务默认id) -->
            <td>
                <div id="div${id}"></div>
                <script type="text/javascript">
                // 根据流程实例id查询流程变量
                $.post("${pageContext.request.contextPath}/processInstanceAction_findData.action",{"id":'${id}'},function(data) {
                    $("#div${id}").html(data);
                });
            </script>
            </td>
            <td>
                <a class="easyui-linkbutton" data-options="iconCls:'icon-search'" onclick="showPng('${id}');" href="#">查看流程图</a>
            </td>
        </tr>
    </s:iterator>
</tbody>

第四步:在ProcessInstanceAction中提供findData()的方法,根据流程实例id查询对应的流程变量数据(ajax)

代码语言:javascript
复制
    // 接收页面提交过来的参数:流程实例id
    private String id;
    public void setId(String id) {
        this.id = id;
    }

    /**
     * 根据流程实例id查询对应的流程变量数据(ajax)
     * @return
     * @throws IOException 
     */
    public String findData() throws IOException {
        Map<String, Object> variables = runtimeService.getVariables(id);
        ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");
        ServletActionContext.getResponse().getWriter().print(variables.toString());
        return "none";
    }

浏览器效果如下图所示:

1.2、查询流程实例运行状态

第一步:为“查看流程图”按钮绑定事件,注意:点击查看流程图按钮,实际上发起了2次请求

代码语言:javascript
复制
    <script type="text/javascript">
        function showPng(id) {
            // 弹出新窗口
            window.open("${pageContext.request.contextPath}/processInstanceAction_showPng.action?id=" + id);
        }
    </script>

第二步:在ProcessInstanceAction中提供showPng()方法,根据流程实例id获取部署id、图片名称、图片坐标

代码语言:javascript
复制
    /**
     * 根据流程实例id获取部署id、图片名称、图片坐标
     * 
     * @return
     */
    public String showPng() {
        // 1、根据流程实例id创建流程实例查询对象
        ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
        query.processInstanceId(id); // 根据流程实例id过滤
        ProcessInstance processInstance = query.singleResult(); // 得到流程实例对象
        // 2、根据流程实例对象获取流程定义id
        String processDefinitionId = processInstance.getProcessDefinitionId();
        // 3、根据流程定义id创建流程定义查询对象 --> 根据流程定义id过滤 --> 得到流程定义对象(链式编程),注意:此方式只查询了流程定义表act_re_procdef
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        // 4、根据流程定义对象获取部署id
        deploymentId = processDefinition.getDeploymentId();
        // 5、根据流程定义对象获取图片名称
        imageName = processDefinition.getDiagramResourceName();
        // 把部署id和图片名称压入值栈后,在image.jsp页面就可以正常获取出来这两个参数,取出来之后该页面又请求新的地址,新的地址又把这两个参数提交过来,我们在Action中又需要接收(设置)这两个参数,是不是有些麻烦呢?
        // 所以针对这种情况,我们需要把部署id和图片名称由局部变量提升为成员变量,并且提供getter和setter方法,终于这两个方法都能用着啦!getter方法用于页面EL表达式获取参数,setter方法用于接收页面提交回来的参数。
        // 因为成员变量本身就在struts的值栈里面,因为struts框架本身将Action对象压入值栈中。

        // 获取坐标
        // 1、获取当前流程实例执行到哪个节点了
        String activityId = processInstance.getActivityId(); // usertask1
        // 2、加载bpmn(xml)文件,获得一个流程定义对象,注意:此方式不仅查询了流程定义表act_re_procdef,还查询了act_ge_bytearray
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId); 
        // 使用流程定义对象的实现类,该实现类里面扩展了很多方法,其中就包括关于坐标的
        // 3、根据activityId获取含有坐标信息的对象
        ActivityImpl findActivity = processDefinitionEntity.findActivity(activityId);
        int x = findActivity.getX();
        int y = findActivity.getY();
        int width = findActivity.getWidth();
        int height = findActivity.getHeight();
        // 将坐标信息压入值栈中
        ActionContext.getContext().getValueStack().set("x", x);
        ActionContext.getContext().getValueStack().set("y", y);
        ActionContext.getContext().getValueStack().set("width", width);
        ActionContext.getContext().getValueStack().set("height", height);

        return "showPng";
    }

第三步:配置struts.xml,跳转到image.jsp页面

代码语言:javascript
复制
    <result name="showPng">/WEB-INF/pages/workflow/image.jsp</result>

第四步:提供image.jsp页面

代码语言:javascript
复制
<body>
    <!-- 1.获取到规则流程图 -->
    <img style="position: absolute;top: 0px;left: 0px;"
         src="processInstanceAction_viewImage?deploymentId=${deploymentId}&imageName=${imageName}">
    <!-- 2.根据当前活动的坐标,动态绘制DIV -->
    <div style="position:absolute;border:1px solid red;top:${y-1}px;left:${x-1}px;width:${width}px;height:${height}px;">
    </div>
</body>

第五步:在ProcessInstanceAction中提供viewImage()方法,根据部署id和图片名称获得对应的输入流

代码语言:javascript
复制
    /**
     * 根据部署id和图片名称获取对应的png输入流
     * @return
     */
    public String viewImage() {
        // 获取png图片对应的输入流
        InputStream pngStream = repositoryService.getResourceAsStream(deploymentId, imageName);
        // 使用Struts框架提供的文件下载功能(文件下载结果集):通过输出流把服务端的资源写到客户端
        // 先把输入流压入值栈,再到页面把流读出来即可
        ActionContext.getContext().getValueStack().set("pngStream", pngStream);
        return "viewImage";
    }

第六步:配置struts.xml

代码语言:javascript
复制
    <result name="viewImage" type="stream">
        <param name="contentType">image/png</param>
        <param name="inputName">pngStream</param><!-- 输入流压栈时起的名字 -->
        <!-- 
        <param name="contentDisposition">attachment;filename="abc.png"</param>
        <param name="bufferSize">1024</param>
         -->
    </result>

浏览器效果如下图所示:

2、将bos系统中的用户和角色同步到activiti框架的用户表和组表中去

2.1、将角色同步到 act_id_group 表中去

修改RoleServiceImpl中的save()方法,如下图所示:

2.2、将用户同步到 act_id_user 表中去

注意:我们在添加用户的时候会选择角色,在activiti框架中对应的是用户表关联组表。 修改UserServiceImpl的save()方法,如下图所示:

3、设计物流配送流程

  • 流程定义的id:
  • 使用排他网关:
  • 使用组任务:
  • 任务的id(对应Action中的方法名):

4、启动物流配送流程

准备工作:

  • 修改工作单类
  • 修改工作单对应的hbm映射文件
  • 为了和我们之前的命名规则一致,修改数据库表auth_function中的“启动配送流程”中的page属性的值为workordermanageAction_list.action

4.1、查询工作单列表数据

第一步:在工作单管理Action中提供list()方法,查询流程状态start为0的工作单(即未启动的工作单)

代码语言:javascript
复制
    /**
     * 查询流程状态start为0的工作单(即未启动的工作单)
     * @return
     */
    public String list() {
        List<Workordermanage> list = workordermanageService.findListNotStart();
        ActionContext.getContext().getValueStack().set("list", list); // 将查询到的结果压栈
        return "list";
    }

Service层代码:

代码语言:javascript
复制
    /**
     * 查询流程状态start为0的工作单(即未启动的工作单)
     */
    public List<Workordermanage> findListNotStart() {
        // 创建离线条件查询对象
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Workordermanage.class);
        // 向离线条件查询对象中封装查询条件
        detachedCriteria.add(Restrictions.eq("start", "0"));
        return workordermanageDao.findByCriteria(detachedCriteria );
    }

第二步:配置struts.xml

代码语言:javascript
复制
    <!-- 工作单管理:配置workordermanageAction-->
    <action name="workordermanageAction_*" class="workordermanageAction" method="{1}">
        <result name="list">/WEB-INF/pages/workflow/startransfer.jsp</result>
    </action>

第三步:提供startransfer.jsp页面,展示工作单列表数据

浏览器显示效果:

4.2、根据key启动流程实例

第一步:修改列表页面中“启动按钮”绑定事件

代码语言:javascript
复制
    <td> 
        <s:a action="workordermanageAction_start" cssClass="easyui-linkbutton" iconCls="icon-edit">启动
            <s:param name="id" value="#workOrderManage.id"></s:param>
        </s:a>
    </td>

第二步:在工作单Action中提供start()方法,启动物流配送流程对应的流程实例 注意:修改工作单中的start值为1,启动流程实例,设置流程变量”为多个数据库表的操作,所以尽量不要在Action中写这么复杂的逻辑,为什么呢? 答:建议写在service里面去,因为涉及到多个数据库表的操作,这样可以保证事务控制。

代码语言:javascript
复制
    /**
     * 启动物流配送流程
     * @return
     */
    public String start() {
        // 获取工作单id
        String id = model.getId();
        // 注意:“修改工作单中的start值为1,启动流程实例,设置流程变量”为多个数据库表的操作,所以尽量不要在Action中写这么复杂的逻辑,为什么呢?
        // 答:建议写在service里面去,因为涉及到多个数据库表的操作,这样可以保证事务控制。
        // 启动流程实例
        workordermanageService.start(id);
        return "toList";
    }

第三步:在工作单Service中提供start()方法,实现数据库操作

代码语言:javascript
复制
    /**
     * 修改工作单中的start值为1,设置流程变量,启动流程实例
     */
    public void start(String workorderId) {
        // 修改工作单中的start值为1
        Workordermanage workordermanage = workordermanageDao.findById(workorderId);
        workordermanage.setStart("1");

        // 设置流程变量
        String processDefinitionKey = "transfer"; // 流程定义key == 画图时给图起的id,这个不需要查询数据库,为已知数据
        String businessKey = workorderId; // 业务主键 == 业务表(工作单)的主键值,因为实际当中携带的数据往往是业务表中数据 ==> 业务主键存在实例流程表中,工作流框架通过业务主键可以找到业务数据
        Map<String, Object> variables = new HashMap<String, Object>(); // 流程变量
        variables.put("业务数据", workordermanage); // 我们在流程变量里面也存一份业务数据,就是说,“业务数据”我可以存在业务主键中,也可以存在流程变量中
        // 启动流程实例
        runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
    }

如下图所示:

5、组任务操作

5.1、查询组任务

第一步:创建一个TaskAction类,提供查询组任务的方法findGroupTask()

代码语言:javascript
复制
    @Autowired
    private TaskService taskService;

    /**
     * 查询组任务
     * @return
     */
    public String findGroupTask() {
        // 创建任务查询对象
        TaskQuery query = taskService.createTaskQuery();
        String candidateUser = BOSContext.getLoginUser().getId(); // 获取当前登录用户的id
        query.taskCandidateUser(candidateUser); // 根据组任务过滤,即根据候选人过滤
        List<Task> list = query.list(); // 执行查询,获得任务列表数据
        // 将任务列表数据压入值栈中
        ActionContext.getContext().getValueStack().set("list", list);
        return "grouptasklist";
    }

第二步:配置struts.xml

代码语言:javascript
复制
    <!-- 任务管理:配置taskAction-->
    <action name="taskAction_*" class="taskAction" method="{1}">
        <result name="grouptasklist">/WEB-INF/pages/workflow/grouptask.jsp</result>
    </action>

第三步:提供grouptask.jsp页面,展示任务列表数据

第三步:在任务Action中,提供显示业务数据的方法showData()

代码语言:javascript
复制
    // 接收页面提交过来的参数:任务id
    private String taskId;
    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    /**
     * 根据任务id查询对应的流程变量数据(ajax)
     * @return
     * @throws IOException 
     */
    public String showData() throws IOException {
        Map<String, Object> variables = taskService.getVariables(taskId);
        ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");
        ServletActionContext.getResponse().getWriter().print(variables.toString());
        return "none";
    }

浏览器显示效果:

5.2、拾取组任务

第一步:修改jsp页面中“拾取按钮”事件

代码语言:javascript
复制
    <td>
        <s:a action="taskAction_takeTask" namespace="/" cssClass="easyui-linkbutton">拾取
            <s:param name="taskId" value="id"></s:param>
        </s:a>
    </td>

第二步:在TaskAction中提供拾取任务的方法takeTask()

代码语言:javascript
复制
    /**
     * 拾取组任务
     * @return
     */
    public String takeTask() {
        String userId = BOSContext.getLoginUser().getId(); // 获取当前登录用户的id
        taskService.claim(taskId, userId);
        return "togrouptasklist";
    }

第三步:配置struts.xml

代码语言:javascript
复制
    <!-- 任务管理:配置taskAction-->
    <action name="taskAction_*" class="taskAction" method="{1}">
        <result name="grouptasklist">/WEB-INF/pages/workflow/grouptask.jsp</result>
        <result name="togrouptasklist" type="redirectAction">
            taskAction_findGroupTask
        </result>
    </action>

6、个人任务操作

6.1、查询个人任务

第一步:在TaskAction中提供findPersonalTask()方法,查询当前登录用户的个人任务

代码语言:javascript
复制
    /**
     * 查询个人任务
     */
    public String findPersonalTask() {
        // 创建任务查询对象
        TaskQuery query = taskService.createTaskQuery();
        String assignee = BOSContext.getLoginUser().getId(); // 获取当前登录用户的id
        query.taskAssignee(assignee); // 根据个人任务过滤
        List<Task> list = query.list(); // 执行查询,获得任务列表数据
        // 将任务列表数据压入值栈中
        ActionContext.getContext().getValueStack().set("list", list);
        return "personaltasklist";
    }

第二步:配置struts.xml

代码语言:javascript
复制
    <result name="personaltasklist">/WEB-INF/pages/workflow/personaltask.jsp</result>

第三步:提供personaltask.jsp页面,展示个人任务列表数据 图片同查询组任务中的第三步。 浏览器显示效果:

6.2、办理个人任务

6.2.1、办理审核工作单任务

第一步:修改personaltask.jsp页面中“办理任务”按钮的事件

第二步:在TaskAction中提供checkWorkOrderManage()方法,办理审核工作单任务

代码语言:javascript
复制
    // 接收页面提交过来的参数:check
    // 审核结果:1 表示审核通过,0表示审核不通过
    private Integer check;
    public Integer getCheck() {
        return check;
    }
    public void setCheck(Integer check) {
        this.check = check;
    }

    /**
     * 办理审核工作单任务(实际上是跳转到审核工作单页面 + 真正办理审核工作单任务)
     */
    public String checkWorkOrderManage() {
        // 根据传递过来的任务id获取任务对象(任务查询对象 --> 根据任务id过滤 --> 任务对象)
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 根据任务对象获取流程实例id
        String processInstanceId = task.getProcessInstanceId();
        // 根据流程实例id获取流程实例对象
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        String workorderId = processInstance.getBusinessKey(); // 业务主键 == 工作单id
        // 根据工作单id获取工作单对象
        Workordermanage workordermanage = workordermanageService.findId(workorderId);

        if (check == null) {
            // 说明需要跳转到审核页面
            // 将工作单数据压入值栈中
            ActionContext.getContext().getValueStack().set("map", workordermanage);
            // 跳转到一个审核工作单页面,展示当前对应的工作单信息
            return "check";
        } else {
            // 真正办理审核工作单任务
            workordermanageService.checkWorkOrderManage(taskId, check, workorderId);
            return "topersonaltasklist"; // 重新回显查询个人任务
        }
    }

第三步:如果是跳转到审核页面,配置struts.xml

代码语言:javascript
复制
    <result name="check">/WEB-INF/pages/workflow/check.jsp</result>

第四步:提供check.jsp页面,展示审核工作单表单页面

第五步:在工作单Service中提供checkWorkOrderManage()方法,处理审核工作单任务 注意:spring配置文件中需要注入historyService。

代码语言:javascript
复制
    // 注入service
    @Autowired
    private TaskService taskService;

    // 注入service
    @Autowired
    private HistoryService historyService;

    /**
     * 办理审核工作单任务
     */
    public void checkWorkOrderManage(String taskId, Integer check, String workorderId) {
        // 如果审核不通过,修改工作单中的start值为0
        Workordermanage workordermanage = workordermanageDao.findById(workorderId);

        // 根据传递过来的任务id获取任务对象(任务查询对象 --> 根据任务id过滤 --> 任务对象)
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 根据任务对象获取流程实例id
        String processInstanceId = task.getProcessInstanceId();

        Map<String, Object> variables = new HashMap<String, Object>();
        // 设置流程变量:check,check会在排他网关中使用
        variables.put("check", check);
        // 办理审核工作单任务
        taskService.complete(taskId, variables);

        if (check == 0) {
            // 说明审核不通过
            workordermanage.setStart("0");
            // 删除历史流程实例数据
            historyService.deleteHistoricProcessInstance(processInstanceId);
        }
    }
6.2.2、办理其他任务

我们简写了。

代码语言:javascript
复制
    /**
     * 办理出库任务
     */
    public String outStore() {
        taskService.complete(taskId);
        return "topersonaltasklist";
    }

    /**
     * 办理配送任务
     */
    public String transferGoods() {
        taskService.complete(taskId);
        return "topersonaltasklist";
    }

    /**
     * 办理签收任务
     */
    public String receive() {
        taskService.complete(taskId);
        return "topersonaltasklist";
    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-10-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、流程实例管理
    • 1.1、查询流程实例
      • 1.2、查询流程实例运行状态
      • 2、将bos系统中的用户和角色同步到activiti框架的用户表和组表中去
        • 2.1、将角色同步到 act_id_group 表中去
          • 2.2、将用户同步到 act_id_user 表中去
          • 3、设计物流配送流程
          • 4、启动物流配送流程
            • 4.1、查询工作单列表数据
              • 4.2、根据key启动流程实例
              • 5、组任务操作
                • 5.1、查询组任务
                  • 5.2、拾取组任务
                  • 6、个人任务操作
                    • 6.1、查询个人任务
                      • 6.2、办理个人任务
                        • 6.2.1、办理审核工作单任务
                        • 6.2.2、办理其他任务
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档