1. 程式人生 > >如何自己實現一個可自定義業務流程步驟的工作流

如何自己實現一個可自定義業務流程步驟的工作流

專案功能需求簡述

由於業務需要,需要一個申請-審批的工作流,並且業務流程是不固定的,需要能靈活配置,比如現在是:開始->部門經理審批->結束,可能之後就會變為開始->部門經理審批->部門領導審批->結束。因此不能把程式碼寫死,必須做成高可配置的。

UML設計

這裡寫圖片描述

專案設計說明

車輛申請專案

一個專案名稱,也可以是其他的,比如請假專案,報銷專案等都可以。主要就是提出申請時需要填寫的表單資訊。

任務列表

當用戶填完申請專案之後,王任務列表中插入一條資料,記錄所屬專案、當前步驟、任務狀態(審批中、任務結束)、使用的流程版本、下一步執行的人,整個任務重申請到結束都只是在更新當前步驟、任務狀態(審批中、任務結束)、下一步執行的人這幾個欄位,其他的都不變。也就是一次申請就只會有一條任務。

歷史任務

每一次申請、或者審批步驟都往裡邊插入一條資料,記錄當前的審判者、步驟、建立時間等資訊。一個申請專案中會有多條記錄。

流程列表

流程的新增,供申請時選擇所屬流程,流程可設定啟用或不啟用狀態。

流程步驟

比如申請車輛這個流程的所有步驟。省內用車:開始->步驟1:部門經理審批->結束;長途用車:開始->步驟1:部門經理審批->步驟2:部門領導審批->結束

步驟處理角色

每個步驟由哪個角色來處理。比如:步驟:部門經理審批——部門經理,步驟:部門領導審批——部門領導。

角色

系統角色,主要做許可權控制。

企業員工

系統使用者。

車輛管理

企業的所有車輛。

初始化資料

角色

這裡寫圖片描述

使用者

這裡寫圖片描述

車輛

這裡寫圖片描述

步驟處理角色

這裡寫圖片描述

流程

這裡寫圖片描述

流程步驟

這裡寫圖片描述

專案流程說明演示

這裡演示一個開始->部門經理審批->部門領導審批->結束的流程

提出申請

先填寫好資訊,再點選確定申請,則開始申請,並往歷史流程和任務列表插入一條資料

這裡寫圖片描述
點選申請
這裡寫圖片描述
插入兩條資料
這裡寫圖片描述
這裡寫圖片描述

自己專案中的程式碼為:


    /**
     * 選澤下一步審批人
     */
    @RequestMapping(value="/submitApply")
    public
ModelAndView submitApply() throws Exception{ logBefore(logger, "提交Apply"); ModelAndView mv = this.getModelAndView(); PageData pd = new PageData(); pd = this.getPageData(); String APPLY_ID=pd.getString("APPLY_ID");//專案ID //根據專案ID查詢專案基本資訊 -> 找出這個專案使用的流程 -> 檢視這個流程的第一步是那哪角色審批 //-> 查詢使用者中是這個角色的所有使用者供選擇 pd.put("nowCount","1"); List<User> userList=userService.listAllUserByApply(pd); mv.setViewName("information/apply/tasklist_chooseUser"); mv.addObject("msg","submitApplyresult"); mv.addObject("pd", pd); mv.addObject("userList",userList); return mv; } /** * 提交申請 * @return * @throws Exception */ @RequestMapping(value="/submitApplyresult") public ModelAndView submitApplyresult() throws Exception{ logBefore(logger, "提交Apply"); ModelAndView mv = this.getModelAndView(); PageData pd = new PageData(); pd = this.getPageData(); String APPLY_ID=pd.getString("APPLY_ID");//專案ID String USER_ID=pd.getString("USER_ID");//選澤的使用者ID //-------------往任務列表中插入一條資料-------------------- pd.put("ITEMID", APPLY_ID); //任務ID pd.put("ACTORID", '1'); //步驟ID: -1表示結束 其他則按照流程定義裡的執行順序來 pd.put("STATE", "稽核流程進行中"); //稽核狀態 PageData pds=applyService.findById(pd); pd.put("VERSION", pds.getString("SQLX")); //流程版本ID 也就是他的申請型別ID pd.put("NextUserID",USER_ID);//下一步審批者ID String TASKLIST_ID=this.get32UUID(); pd.put("TASKLIST_ID",TASKLIST_ID ); //主鍵ID tasklistService.save(pd); //-------------往歷史任務列表中插入一條資料-------------------- Subject currentUser = SecurityUtils.getSubject();//shiro管理的session Session session = currentUser.getSession(); String USERNAME = session.getAttribute(Const.SESSION_USERNAME).toString(); //獲取當前登入者loginname pd.put("ITEMID", APPLY_ID); //任務ID pd.put("ACTORID","0"); //步驟ID:-1表示結束 其他則按照流程定義裡的執行順序來 pd.put("MEMO", USERNAME+"提出申請"); //備註 pd.put("OPERATEUSERID", USERNAME); //操作人 pd.put("CREATEDATE", DateUtil.getTime()); //操作建立時間 String TASKHISTORY_ID=this.get32UUID(); pd.put("TASKHISTORY_ID",TASKHISTORY_ID ); //主鍵ID taskHistoryService.save(pd); //-----------------------------------------------------// mv.addObject("msg","success"); mv.setViewName("save_result"); return mv; }

部門經理審批

有待審批任務的人點選待我審批任務後就會列出來
這裡寫圖片描述

在稽核介面可以選擇同意或者拒絕
如果同意的話會判斷目前是不是最後一個步驟,是就選澤車輛,不是就選擇下一步的處理角色。
如果不同意的話則直接結束流程。

目前還不是最後一步
這裡寫圖片描述
更新任務列表
這裡寫圖片描述
歷史任務插入一條資料
這裡寫圖片描述

部門領導審批

部門領導以及是這個審批流程中的最後一個審批
所以選擇車輛而不是下一步處理人
這裡寫圖片描述
更新任務列表
這裡寫圖片描述
插入歷史紀錄
這裡寫圖片描述

審批程式碼

部門經理審批和部門領導審批的程式碼都是一樣的,就算在新增其他流程程式碼也是不需要修改的。

/**
     * 選擇下一步審批人,流程繼續
     */
    @RequestMapping(value="/taskSubmitApply")
    public ModelAndView taskSubmitApply() throws Exception{
        logBefore(logger, "提交Apply");
        ModelAndView mv = this.getModelAndView();
        PageData pd = new PageData();
        pd = this.getPageData();
        String APPLY_ID=pd.getString("APPLY_ID");//專案ID

        //根據專案ID查詢專案基本資訊 -> 找出這個專案使用的流程 -> 檢視這個流程的第一步是那哪角色審批
        //-> 查詢使用者中是這個角色的所有使用者供選擇
        int nowCount=tasklistService.findNowCount(pd);//當前步驟
        int allCount=tasklistService.findCount(pd);//總的步驟

        if(allCount==nowCount){//供頁面判斷是否是最後
            pd.put("iSLast",1);
        }else pd.put("iSLast",0);

        pd.put("nowCount",nowCount+1);
        List<User> userList=userService.listAllUserByApply(pd);
        List<Car> carList=carService.carlistAll();

        //如果當前次數+1是最後一次,則進入派車頁面
//      if(nowCount+1==tasklistService.findCount(pd)){
//          mv.setViewName("information/car/list");
//          mv.addObject("msg","tasklist/submitApplyresult");
//          mv.addObject("pd", pd);
//      }else {//否則進入設定下一個審批者頁面


            mv.setViewName("information/tasklist/tasklist_chooseUser");

            mv.addObject("pd", pd);
            mv.addObject("userList",userList);
            mv.addObject("carList",carList);

        if(allCount==nowCount) {//供頁面判斷是最後
            mv.addObject("msg","endtaskSubmitApplyresult");//同意 繼續下一步的角色選擇
        }else {
            mv.addObject("msg","taskSubmitApplyresult");//最後一個派車同意 繼續下一步的角色選擇
        }

        return mv;
    }

    /**
     * 同意派車,流程結束
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/endtaskSubmitApplyresult")
    public ModelAndView endtaskSubmitApplyresult() throws Exception{
        logBefore(logger, "提交Apply");
        ModelAndView mv = this.getModelAndView();
        PageData pd = new PageData();
        pd = this.getPageData();

        String APPLY_ID=pd.getString("APPLY_ID");//專案ID
        String Car_ID=pd.getString("Car_ID");//選澤的車輛ID
        String TASKLIST_ID=pd.getString("TASKLIST_ID");//當前任務ID

        //-------------更新任務列表的下一個審批者和下一步的步驟ID--------------------

        int nowCount=tasklistService.findNowCount(pd);
        int allCount=tasklistService.findCount(pd);

//      if(nowCount<allCount){
        pd.put("ACTORID", -1);  //步驟ID: -1表示結束  其他則按照流程定義裡的執行順序來
        pd.put("STATE", "流程結束,請提取車輛:"+Car_ID);  //稽核狀態
        pd.put("NextUserID","");//下一步審批者ID
        pd.put("TASKLIST_ID",TASKLIST_ID ); //主鍵ID
        tasklistService.edit(pd);

        //-------------往歷史任務列表中插入一條資料--------------------

        Subject currentUser = SecurityUtils.getSubject();//shiro管理的session
        Session session = currentUser.getSession();
        String USERNAME = session.getAttribute(Const.SESSION_USERNAME).toString();  //獲取當前登入者loginname

        pd.put("ITEMID", APPLY_ID); //任務ID
        pd.put("ACTORID",nowCount); //步驟ID:-1表示結束  其他則按照流程定義裡的執行順序來
        pd.put("MEMO", USERNAME+"同意申請,稽核流程結束"); //備註
        pd.put("OPERATEUSERID", USERNAME);  //操作人
        pd.put("CREATEDATE", DateUtil.getTime());   //操作建立時間
        String TASKHISTORY_ID=this.get32UUID();
        pd.put("TASKHISTORY_ID",TASKHISTORY_ID );   //主鍵ID
        taskHistoryService.save(pd);
        //-----------------------------------------------------//

        mv.addObject("msg","success");
        mv.setViewName("save_result");
        return mv;
    }

    /**
     * 同意的稽核,繼續下一個審批人選澤,流程繼續
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/taskSubmitApplyresult")
    public ModelAndView taskSubmitApplyresult() throws Exception{
        logBefore(logger, "提交Apply");
        ModelAndView mv = this.getModelAndView();
        PageData pd = new PageData();
        pd = this.getPageData();

        String APPLY_ID=pd.getString("APPLY_ID");//專案ID
        String USER_ID=pd.getString("USER_ID");//選澤的使用者ID
        String TASKLIST_ID=pd.getString("TASKLIST_ID");//當前任務ID

        //-------------更新任務列表的下一個審批者和下一步的步驟ID--------------------

        int nowCount=tasklistService.findNowCount(pd);
        int allCount=tasklistService.findCount(pd);

//      if(nowCount<allCount){
            pd.put("ACTORID", nowCount+1);  //步驟ID: -1表示結束  其他則按照流程定義裡的執行順序來
            pd.put("STATE", "稽核流程進行中"); //稽核狀態
            pd.put("NextUserID",USER_ID);//下一步審批者ID
            pd.put("TASKLIST_ID",TASKLIST_ID ); //主鍵ID
            tasklistService.edit(pd);
//      }else {
//          pd.put("ACTORID", "-1");    //步驟ID: -1表示結束  其他則按照流程定義裡的執行順序來
//          pd.put("STATE", "稽核流程結束");  //稽核狀態
//          pd.put("NextUserID","");//下一步審批者ID
//          pd.put("TASKLIST_ID",TASKLIST_ID ); //主鍵ID
//          tasklistService.edit(pd);
//      }




        //-------------往歷史任務列表中插入一條資料--------------------

        Subject currentUser = SecurityUtils.getSubject();//shiro管理的session
        Session session = currentUser.getSession();
        String USERNAME = session.getAttribute(Const.SESSION_USERNAME).toString();  //獲取當前登入者loginname

        pd.put("ITEMID", APPLY_ID); //任務ID
        pd.put("ACTORID",nowCount); //步驟ID:-1表示結束  其他則按照流程定義裡的執行順序來
        pd.put("MEMO", USERNAME+"同意申請");    //備註
        pd.put("OPERATEUSERID", USERNAME);  //操作人
        pd.put("CREATEDATE", DateUtil.getTime());   //操作建立時間
        String TASKHISTORY_ID=this.get32UUID();
        pd.put("TASKHISTORY_ID",TASKHISTORY_ID );   //主鍵ID
        taskHistoryService.save(pd);
        //-----------------------------------------------------//

        mv.addObject("msg","success");
        mv.setViewName("save_result");
        return mv;

    }


    /**
     * 不同意的稽核,流程結束
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/refuseapply")
    public ModelAndView refuseapply() throws Exception{
        logBefore(logger, "提交Apply");
        ModelAndView mv = this.getModelAndView();
        PageData pd = new PageData();
        pd = this.getPageData();

        String APPLY_ID=pd.getString("APPLY_ID");//專案ID
        String TASKLIST_ID=pd.getString("TASKLIST_ID");//當前任務ID

        pd.put("ACTORID", "-1");    //步驟ID: -1表示結束  其他則按照流程定義裡的執行順序來
        pd.put("STATE", "流程結束");    //稽核狀態
        pd.put("NextUserID","");//下一步審批者ID
        pd.put("TASKLIST_ID",TASKLIST_ID ); //主鍵ID
        tasklistService.edit(pd);

        //-------------往歷史任務列表中插入一條資料--------------------

        Subject currentUser = SecurityUtils.getSubject();//shiro管理的session
        Session session = currentUser.getSession();
        String USERNAME = session.getAttribute(Const.SESSION_USERNAME).toString();  //獲取當前登入者loginname

        pd.put("ITEMID", APPLY_ID); //任務ID
        pd.put("ACTORID","-1"); //步驟ID:-1表示結束  其他則按照流程定義裡的執行順序來
        pd.put("MEMO", USERNAME+"不同意申請");   //備註
        pd.put("OPERATEUSERID", USERNAME);  //操作人
        pd.put("CREATEDATE", DateUtil.getTime());   //操作建立時間
        String TASKHISTORY_ID=this.get32UUID();
        pd.put("TASKHISTORY_ID",TASKHISTORY_ID );   //主鍵ID
        taskHistoryService.save(pd);
        //-----------------------------------------------------//

        mv.addObject("msg","success");
        mv.setViewName("save_result");
        return mv;
    }