本周我学习如何使用芋道开源项目在原有的项目基础上进行新的报销流程开发,我在此总结一下学习过程及心得。

首先由于公司的电脑不允许安装软件,我在安装最新的vue项目时无法install,故使用的是导师之前使用的版本,可能略有不同。

项目描述:前端使用vue2.6.12、element ui、node.js16版本,后端使用Spring boot、Spring security等框架。

模块描述:根据要求搭建报销流程(两个审批节点(以报销金额为条件区分)),使用代码生成器生成代码及相关表单并与流程对接。

根据开发文档描述,需要先创建我们要用到的数据库表,以下是我的数据库文件代码。

1 /*
 2  Navicat Premium Data Transfer
 3 
 4  Source Server         : localhost_3306
 5  Source Server Type    : MySQL
 6  Source Server Version : 50739
 7  Source Host           : localhost:3306
 8  Source Schema         : ruoyi-vue-pro
 9 
10  Target Server Type    : MySQL
11  Target Server Version : 50739
12  File Encoding         : 65001
13 
14  Date: 28/07/2022 15:22:17
15 */
16 
17 SET NAMES utf8mb4;
18 SET FOREIGN_KEY_CHECKS = 0;
19 
20 -- ----------------------------
21 -- Table structure for bpm_oa_baoxiao
22 -- ----------------------------
23 DROP TABLE IF EXISTS `bpm_oa_baoxiao`;
24 CREATE TABLE `bpm_oa_baoxiao`  (
25   `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '报销表单主键',
26   `user_id` bigint(20) NOT NULL COMMENT '申请人的用户编号',
27   `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '备注',
28   `apply_time` datetime NOT NULL COMMENT '申请时间',
29   `money` decimal(18,2) NOT NULL COMMENT '报销金额',
30   `result` tinyint(4) NOT NULL COMMENT '报销结果',
31   `process_instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '流程实例的编号',
32   `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
33   `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
34   `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
35   `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
36   `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
37   PRIMARY KEY (`id`) USING BTREE
38 ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OA 请假申请表' ROW_FORMAT = Dynamic;
39 
40 SET FOREIGN_KEY_CHECKS = 1;

 在基础设施-->代码生成下选择我们的数据库表,之后编辑我们需要在页面中展示的功能,如每个属性在页面中需要的增删改查功能以及需要的表单形态等。将自动生成的代码复制进后端程序中,前端项目也复制进程序中。然后使用debug模式重启项目先测试是否有报错,查看接口启动情况。

前端我们代码自动生成的只有index页面,这时我们还需要创建create和detail页面,因为我们在后面创建流程和审批查看流程时都需要跳转到相应的页面。在router/index.js下定义这两个页面的路由。

{
    path: '/bpm',
    component: Layout,
    hidden: true,
    redirect: 'noredirect',
    children: [{
        path: 'oa/oaBaoxiao/create',
        component: (resolve) => require(['@/views/bpm/oa/oaBaoxiao/create'], resolve),
        name: '发起 OA 报销',
        meta: {title: '发起 OA 报销', icon: 'form', activeMenu: '/bpm/oa/oaBaoxiao'}
      }, {
        path: 'oa/leave/detail',
        component: (resolve) => require(['@/views/bpm/oa/oaBaoxiao/detail'], resolve),
        name: '查看 OA 报销',
        meta: {title: '查看 OA 报销', icon: 'view', activeMenu: '/bpm/oa/oaBaoxiao'}
      }
    ]
}

 

后端在配置时还需要配置一个监听器,对流程实例监听,在结束时回调通知结果。

@Component
public class OaBaoxiaoResultListener extends BpmProcessInstanceResultEventListener {

    @Resource
    private OaBaoxiaoService baoxiaoService;


    @Override
    protected String getProcessDefinitionKey() {
        return OaBaoxiaoServiceImpl.PROCESS_KEY;
    }

    @Override
    protected void onEvent(BpmProcessInstanceResultEvent event) {
        baoxiaoService.updateOaBaoxiaoResult(Long.parseLong(event.getBusinessKey()), event.getResult());
    }
}

 

在前面我尝试过表单流程创建,创建过程中有一个条件流转条件也就是金额大小来判断是否需要二级领导审批,在业务表单中我们和流程关联的方式就是在我们创建需要的报销流程时,同时创建对应的流程实例,如下代码中,在创建流程实例时我们根据设置的流程标识来关联到对应流程并生成对应的流程实例id存到对应的报销申请表中。此时我们的报销流程中包含了所需要的报销金额,在与流程关联后会判断金额之后判定流转条件。

// 插入报销表单
        OaBaoxiaoDO oaBaoxiao = OaBaoxiaoConvert.INSTANCE.convert(createReqVO).setUserId(id)
                .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
        oaBaoxiaoMapper.insert(oaBaoxiao);
        //创建流程实例
        Map<String,Object> processInstanceVariables = new HashMap<>();
        processInstanceVariables.put("money",createReqVO.getMoney());
        String processInstanceId = processInstanceApi.createProcessInstance(id,
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                    .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(oaBaoxiao.getId())));

        oaBaoxiaoMapper.updateById(new OaBaoxiaoDO().setId(oaBaoxiao.getId()).setProcessInstanceId(processInstanceId));

接下来继续定义流程,在新建流程之后需要注意流程标识要和我们Java代码中定义的key保持一致,才能保证流程实例创建成功。接下来选择表单类型时选择业务表单,填写表单路由为我们前面创建的create和detail页面。

然后设计流程,在设计流程时因为需要条件判断所以需要考虑到添加路由来判断流转条件,从数据中找到金额的关键字money,进行大小判断。之后分配角色,根据现有的角色或者自定义角色来进行审批。

发布流程之后即可进行报销流程申请。

易错总结:

(1)由于自动生成代码的弊端,VO和DO在生成时可能没有我们需要在页面上展示的数据,此时我们在页面获取数据时可能会遇到undefined或者获取不到的问题。

(2)我们在配置路由或者路径时可能会有访问的路径和实际路径不一致的问题,可能是由于我们将文件夹的位置发生了改变,在文件位置发生变化之后要去系统管理-->菜单管理中对路径进行更改。

(3)在新建流程实例时,创建流程名可能失败,根据导师帮助查找发现在创建时会发送通知,由于未知原因无法发送,导致卡在这一步,将代码注释后解决。

(4)创建流程时需要判断条件时要用到路由,加入路由后对流转条件进行添加。