zoukankan      html  css  js  c++  java
  • day59_BOS项目_11

    • 今天内容安排:
      • 1、流程实例管理(查询流程实例、查看流程实例运行状态)
      • 2、将bos系统中的用户和角色同步到activiti框架的用户表和组表中去
      • 3、设计物流配送流程
      • 4、启动物流配送流程
      • 5、组任务操作(查询、拾取)
      • 6、个人任务操作(查询、办理)

    1、流程实例管理

    1.1、查询流程实例

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

        // 注入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

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

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

    <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)

        // 接收页面提交过来的参数:流程实例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次请求

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

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

        /**
         * 根据流程实例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页面

        <result name="showPng">/WEB-INF/pages/workflow/image.jsp</result>

    第四步:提供image.jsp页面

    <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}px;height:${height}px;">
        </div>
    </body>

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

        /**
         * 根据部署id和图片名称获取对应的png输入流
         * @return
         */

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

    第六步:配置struts.xml

        <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的工作单(即未启动的工作单)

        /**
         * 查询流程状态start为0的工作单(即未启动的工作单)
         * @return
         */

        public String list() {
            List<Workordermanage> list = workordermanageService.findListNotStart();
            ActionContext.getContext().getValueStack().set("list"list); // 将查询到的结果压栈
            return "list";
        }

    Service层代码:

        /**
         * 查询流程状态start为0的工作单(即未启动的工作单)
         */

        public List<Workordermanage> findListNotStart() {
            // 创建离线条件查询对象
            DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Workordermanage.class);
            // 向离线条件查询对象中封装查询条件
            detachedCriteria.add(Restrictions.eq("start""0"));
            return workordermanageDao.findByCriteria(detachedCriteria );
        }

    第二步:配置struts.xml

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

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


    浏览器显示效果:

    4.2、根据key启动流程实例

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

        <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里面去,因为涉及到多个数据库表的操作,这样可以保证事务控制。

        /**
         * 启动物流配送流程
         * @return
         */

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

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

        /**
         * 修改工作单中的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<StringObject> variables = new HashMap<StringObject>(); // 流程变量
            variables.put("业务数据", workordermanage); // 我们在流程变量里面也存一份业务数据,就是说,“业务数据”我可以存在业务主键中,也可以存在流程变量中
            // 启动流程实例
            runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
        }

    如下图所示:

    5、组任务操作

    5.1、查询组任务

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

        @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

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

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


    第三步:在任务Action中,提供显示业务数据的方法showData()
        // 接收页面提交过来的参数:任务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页面中“拾取按钮”事件

        <td>
            <s:a action="taskAction_takeTask" namespace="/" cssClass="easyui-linkbutton">拾取
                <s:param name="taskId" value="id"></s:param>
            </s:a>
        </td>

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

        /**
         * 拾取组任务
         * @return
         */

        public String takeTask() {
            String userId = BOSContext.getLoginUser().getId(); // 获取当前登录用户的id
            taskService.claim(taskId, userId);
            return "togrouptasklist";
        }

    第三步:配置struts.xml

        <!-- 任务管理:配置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()方法,查询当前登录用户的个人任务

        /**
         * 查询个人任务
         */

        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

        <result name="personaltasklist">/WEB-INF/pages/workflow/personaltask.jsp</result>

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

    6.2、办理个人任务

    6.2.1、办理审核工作单任务

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


    第二步:在TaskAction中提供checkWorkOrderManage()方法,办理审核工作单任务
        // 接收页面提交过来的参数: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

        <result name="check">/WEB-INF/pages/workflow/check.jsp</result>

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


    第五步:在工作单Service中提供checkWorkOrderManage()方法,处理审核工作单任务
    注意:spring配置文件中需要注入historyService。
        // 注入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<StringObject> variables = new HashMap<StringObject>();
            // 设置流程变量:check,check会在排他网关中使用
            variables.put("check", check);
            // 办理审核工作单任务
            taskService.complete(taskId, variables);

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

    6.2.2、办理其他任务

    我们简写了。

        /**
         * 办理出库任务
         */

        public String outStore() {
            taskService.complete(taskId);
            return "topersonaltasklist";
        }

        /**
         * 办理配送任务
         */

        public String transferGoods() {
            taskService.complete(taskId);
            return "topersonaltasklist";
        }

        /**
         * 办理签收任务
         */

        public String receive() {
            taskService.complete(taskId);
            return "topersonaltasklist";
        }
  • 相关阅读:
    ios专题 - CocoaPods - 初次体验
    ios专题 - CocoaPods - 安装
    Objective-C浅拷贝和深拷贝
    支付宝交互流程
    UITabBar的隐藏
    iOS-容易造成循环引用的三种场景
    FMDB 的基本操作
    Swap file ".Podfile.swp" already exists!
    将UIImage保存成JPG或PNG格式存储在本地
    UI常用控件的一些属性
  • 原文地址:https://www.cnblogs.com/chenmingjun/p/9815207.html
Copyright © 2011-2022 走看看