前兩天我們已經(jīng)完成了流程定義的管理和表單的定義的管理。今天們將整合這兩大模塊,使他們形成一個(gè)標(biāo)準(zhǔn)的工作流程。
在學(xué)習(xí)OA項(xiàng)目時(shí),就像學(xué)習(xí)其他知識一樣跟著老師的思路走。有的時(shí)候東西講的比較多就一頭霧水,這是正常的。但最近我在寫學(xué)習(xí)總結(jié)時(shí)候發(fā)現(xiàn)老師講的東西很簡單,為什么我們會(huì)一頭霧水?原因一,我們用錯(cuò)的學(xué)習(xí)方法。首先老師講的是什么他已經(jīng)給了我們框架了,所以在老師講某個(gè)東西時(shí)我們要在自己的腦子里有一個(gè)宏觀的實(shí)現(xiàn)框架。然后再去聽細(xì)節(jié),這樣老師無論怎么講我們都在自己的框架內(nèi)。如果自己的框架錯(cuò)了就改一下。原因二,我們畏懼新知識,未知領(lǐng)域是我們意象中的巨大敵人。這是錯(cuò)誤的,我們應(yīng)該像毛澤東主席那樣,我們應(yīng)該藐視敵人。
你知道嗎?我近兩天就使用這樣的方法,老師講什么我先在自己的腦子中有框架。然后十分藐視OA項(xiàng)目,我看它看得非常簡單。當(dāng)老師講完某一應(yīng)用時(shí),我發(fā)現(xiàn)自己的框架和實(shí)現(xiàn)過程是完全正確的。我應(yīng)該繼續(xù)保持和提升這樣的方法,加強(qiáng)以后的工作和學(xué)習(xí)效率。
只要我們用心去體會(huì)與發(fā)現(xiàn)身邊的事物,我們就可以從他們身上獲得更多的知識。我寫日志本想是能在文字和文章結(jié)構(gòu)上有所提升,但現(xiàn)在提升的遠(yuǎn)不只這些。清晰的思路,對知識點(diǎn)的掌握…。
今日的重點(diǎn)內(nèi)容是將表單實(shí)例與流程實(shí)例整合運(yùn)行,關(guān)于各申請信息的查詢在此就不做總結(jié)了。
一、審批流轉(zhuǎn)之起草申請
起草申請便是將所有添加的申請表單列出來,然后用戶選擇相應(yīng)的申請表單并填寫,然后提交申請:

下面我們來看一下ApprovalflowAction的實(shí)現(xiàn):
1.起草申請
/** * 起草申請(表單定義列表) */ public ActionForward list(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取表單定義列表 List<FormDefinition> formDefinitionList = formDefinitionService .findAll(); request.setAttribute("formDefinitionList", formDefinitionList); return mapping.findForward("list"); // list.jsp } |
有關(guān)service的實(shí)現(xiàn),我就不列出來了,因?yàn)槟鞘趾唵巍?/span>
2.申請頁面
我們應(yīng)該如何顯示自定義表單?在“FormDefinition”實(shí)體中有一個(gè)“templatePath”屬性,我們在顯示頁面調(diào)用“<jsp:include page="${formInstance.formDefinition.templatePath}"/>”即可顯示相關(guān)表單。
/** * 申請頁面(填寫表單的頁面) */ public ActionForward applyUI(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取表單定義ID Long id = Long.parseLong(request.getParameter("formDefinitionId")); // 獲取表單文件路徑 FormDefinition formDefinition = formDefinitionService.getById(id); return new ActionForward(formDefinition.getTemplatePath()); } |
3.提交申請
/** * 提交表單 */ public ActionForward apply(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取表單定義 Long formDefinitionId = Long.parseLong(request .getParameter("formDefinitionId")); FormDefinition formDefinition = formDefinitionService .getById(formDefinitionId); // 獲取當(dāng)前用戶 User user = (User) request.getSession().getAttribute("user"); // 創(chuàng)建表單實(shí)例 FormInstance formInstance = new FormInstance(); formInstance.setApplicant(user.getEmployee()); formInstance.setApplyTime(new Date()); formInstance.setFormDefinition(formDefinition); // 保存表單數(shù)據(jù) for (String name : formDefinition.getFieldDefinitionList().keySet()) { String strValue = request.getParameter(name); Class valueType = formDefinition.getFieldDefinitionList().get(name); Converter converter = ConvertUtils.lookup(valueType); Serializable value = (Serializable) converter.convert(valueType, strValue); formInstance.getPropertyMap().put(name, value); } // 提交 formInstanceService.submitFormInstance(formInstance); // 轉(zhuǎn)到我的申請列表 return mapping.findForward("toMyApplicationList"); } |
我們有必要,列出“submitFormInstance”方法的實(shí)現(xiàn)。提交申請后,我們需要將申請數(shù)據(jù)保存到數(shù)據(jù)庫中。并開啟流程,使流程開始流轉(zhuǎn):
/** * 保存申請并開始流轉(zhuǎn) */ public void submitFormInstance(FormInstance formInstance) { // 保存表單數(shù)據(jù) getSession().save(formInstance); //------------------開啟流程--------------- // 創(chuàng)建流程實(shí)例 ProcessDefinition pd = getJbpmContext().getGraphSession().findLatestProcessDefinition("leave"); ProcessInstance pi = pd.createProcessInstance(); // 設(shè)置變量 String applicantActorId = formInstance.getApplicant().getId().toString(); // 第一個(gè)任務(wù)分配給(在這里是申請人) pi.getContextInstance().setVariable("applicantActorId", applicantActorId); // 申請的數(shù)據(jù) pi.getContextInstance().setVariable("formInstance", formInstance); // 更新FormInstance // 標(biāo)題格式:{表單名稱}_{申請人姓名}_{申請日期} formInstance.setTitle(formInstance.getFormDefinition().getName() + "_" + formInstance.getApplicant().getName() + "_"// + sdf.format(formInstance.getApplyTime())); // 設(shè)置狀態(tài)為:正在流轉(zhuǎn)... formInstance.setStatus(FormInstance.STATUS_PROCESSING); formInstance.setProcessInstanceId(pi.getId()); // Signal pi.signal(); // 辦理任務(wù):提交申請 TaskInstance ti = (TaskInstance) pi.getTaskMgmtInstance()// .getUnfinishedTasks(pi.getRootToken())// .iterator().next(); ti.start(); // 此處會(huì)自動(dòng)將下一個(gè)任務(wù)觸發(fā)(保存到數(shù)據(jù)庫中) ti.end(); } |
OK,上面就完成了起草申請的整個(gè)過程!
二、審批流轉(zhuǎn)之待我審批
待我審批,查看數(shù)據(jù)庫中的任務(wù)記錄,那些分配給“我”(由“我”負(fù)責(zé))的任務(wù),便是待我審批的任務(wù)。
1.待我審批
/** * 待我審批(我的任務(wù)列表) */ public ActionForward taskList(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取當(dāng)前頁碼 int pageNum = RequestUtils.getIntParam(request, "pageNum", 1); // 獲取當(dāng)前用戶 User user = (User) request.getSession().getAttribute("user"); // 當(dāng)前用戶 未完成的 任務(wù)列表 PageView pageView = formInstanceService.getTaskPageView(user .getEmployee(), pageNum); request.setAttribute("pageView", pageView); return mapping.findForward("taskList"); } |
其中的“formInstanceService.getTaskPageView”如下:
// 查詢TaskInfo的列表 @SuppressWarnings("unchecked") public PageView getTaskPageView(Employee employee, int pageNum) { int pageSize = 10; // 獲取待我審批的任務(wù)數(shù)量 int count = ((Number) getSession().createQuery(// "SELECT COUNT(ti) FROM org.jbpm.taskmgmt.exe.TaskInstance ti WHERE actorId=? AND ti.end IS NULL")// .setParameter(0, employee.getId().toString())// .uniqueResult())// .intValue(); // 獲取待我審批的任務(wù)列表 int firstResult = PageView.calcFirstResult(pageNum, pageSize); List<TaskInstance> taskInstanceList = getSession().createQuery(// "FROM org.jbpm.taskmgmt.exe.TaskInstance ti WHERE actorId=? AND ti.end IS NULL")// .setParameter(0, employee.getId().toString())// .setFirstResult(firstResult)// .setMaxResults(pageSize)// .list(); // 頁面中需要顯示表單實(shí)例信息,且僅需要任務(wù)實(shí)例的ID List<FormInstance> formInstanceList = new ArrayList<FormInstance>(); for (TaskInstance ti : taskInstanceList) { FormInstance formInstance = (FormInstance) ti.getContextInstance().getVariable("formInstance"); formInstance.setCurrentTaskInstanceId(ti.getId()); formInstanceList.add(formInstance); } // 顯示 return new PageView(pageNum, pageSize, count, formInstanceList); } |
2.審批頁面
/** * 審批頁面 */ public ActionForward approveUI(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取表單實(shí)例ID Long formInstanceId = Long.parseLong(request .getParameter("formInstanceId")); // 獲取表單實(shí)例,表單實(shí)例包含審批信息 FormInstance formInstance = formInstanceService.getById(formInstanceId); request.setAttribute("formInstance", formInstance); return mapping.findForward("approveUI"); } |
3.審批
/** * 審批 */ public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取表單數(shù)據(jù) ApproveInfoActionForm actionForm = (ApproveInfoActionForm) form; FormInstance formInstance = formInstanceService.getById(actionForm .getFormInstanceId()); // 獲取當(dāng)前用戶 User user = (User) request.getSession().getAttribute("user"); // 創(chuàng)建審批信息 ApproveInfo approveInfo = new ApproveInfo(); approveInfo.setApprover(user.getEmployee()); approveInfo.setApproveTime(new Date()); approveInfo.setApproval(actionForm.isApproval()); approveInfo.setComment(actionForm.getComment()); approveInfo.setTaskInstanceId(actionForm.getTaskInstanceId()); approveInfo.setFormInstance(formInstance); // 審批 formInstanceService.approve(approveInfo); return mapping.findForward("toTaskList"); } |
其中的“formInstanceService.approve”如下:
/** * 審批 */ public void approve(ApproveInfo approveInfo) { // 保存審批信息 getSession().save(approveInfo); // 辦理任務(wù):審批 FormInstance formInstance = approveInfo.getFormInstance(); TaskInstance ti = getJbpmContext().getTaskInstance(approveInfo.getTaskInstanceId()); ProcessInstance pi = ti.getProcessInstance(); // 如果未通過 if (!approveInfo.isApproval()) { // 停止任務(wù)向下流轉(zhuǎn) ti.setSignalling(false); ti.start(); ti.end(); // 結(jié)束流程實(shí)例 pi.end(); // 設(shè)置流程狀態(tài)為“未通過審批” formInstance.setStatus(FormInstance.STATUS_NOT_APPROVED); } // 如果審批通過 else { // 正常執(zhí)行任務(wù),向下流轉(zhuǎn) ti.start(); ti.end(); // 如果流程已結(jié)束, 就代表本次為最后一個(gè)審批 if (pi.hasEnded()) { // 設(shè)置流程狀態(tài)為“已通過審批” formInstance.setStatus(FormInstance.STATUS_APPROVED); } } // 需要手動(dòng)更新流程數(shù)據(jù)(如果FormInstance的lazy屬性為false呢?。?/span> getSession().update(formInstance); } |
OK,待我審批完成!
三、表單查詢
這部分的內(nèi)容有“我的申請”、“經(jīng)我審批”和“所有表單”,其中涉及條件查詢在此就不一一總結(jié)了。不過這些模塊中有一個(gè)十分有趣的功能——“查看流程圖”。
在以前的工作中,我經(jīng)涉及到圖片和畫板的應(yīng)用開發(fā)。我的查看流程圖思路是將圖片畫到畫板上然后根據(jù)坐標(biāo)信息(gpd.xml)畫出對應(yīng)流程模塊的矩形,然后保存圖板圖,最后將圖片顯示到頁面。但湯老師的實(shí)現(xiàn)比較優(yōu)雅,直接將流程圖顯示到頁面,然后向頁面中添加一個(gè)div,并設(shè)置div的坐標(biāo)、尺寸和邊框顏色。
由此可見,我還需要一些工作經(jīng)驗(yàn)將這些技術(shù)熟練掌握!
通過OA項(xiàng)目的學(xué)習(xí),使我知道應(yīng)該如何學(xué)習(xí)下一個(gè)項(xiàng)目——《教育辦公系統(tǒng)》。希望自己能將這個(gè)系統(tǒng)做的更好!
加油!