首页 > 其他分享 >OA自动化办公: springboot集成Activiti7

OA自动化办公: springboot集成Activiti7

时间:2024-06-21 17:58:40浏览次数:23  
标签:task springboot NPC String Activiti7 OA import id Result

一.场景引入

        我在实际开发中遇到过这样一个需求:公民登录建议征集系统向大冶市某个人大代表提建议,但建议提出后人大代表未能及时响应,此时如果建议越来越多,就会导致建议被搁置。很多建议不会被处理,公民自然也就得不到反馈,这对于汇聚民生民意和征集建议显然是不利的。于是,我开始构思:能否利用工作流的技术,当有公民的建议提交给人大代表的时候就创建一个流程实例,如果建议超过时间没有被处理,系统自动将建议转交到人大组,同组的人大可以拾取和处置该建议(我以地区作为分组,例如:张三,李四,王五为大冶市人大代表,赵六,王伟为黄石港区人大代表。公民提交建议到张三账号后张三未能及时对建议作出处理,建议超过7天就会自动转交到与张三同为大冶市人大代表的人大组代表中。也就是说,建议提出后7天内建议由张三处理,李四,王五以及其他人大无权查看和处置。建议超过7天后,李四,王五(大冶市人大代表)账号可以看到这条超时未被处理的建议,拾取和处置建议,张三可以重新拾取和处置已经超时的建议(任务);赵六,王伟(黄石港区人大)账号始终不能看到提交到大冶市人大代表的建议)。

       还有,对于超时的建议(任务),人大代表必须先拾取再处置,如果拾取后的建议并不擅长处理,可以将建议(任务)归还,此后(建议)任务回到可拾取任务队列中,可以由同组的其他人大拾取和处置。如此往复......直至建议被解决。

      定下需求后,我开始着手于实现。但是我发现网上的资源较少,不能支持我完整的开发出这样的功能,于是我开始自己摸索,买书,看网课,不断测试......完成了这个需求。

      下面是我使用springboot框架集成Activiti7完成开发的过程:

1.开发所要用到的Maven依赖

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <version>7.1.0.M4</version>
    <exclusions>
        <exclusion>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.activiti.dependencies</groupId>
    <artifactId>activiti-dependencies</artifactId>
    <version>7.1.0.M4</version>
    <type>pom</type>
</dependency>

<!-- 生成流程图 -->
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-image-generator</artifactId>
    <version>7.1.0.M4</version>
</dependency>

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-process-validation</artifactId>
    <version>7.1.0.M4</version>
</dependency>

 2.下载BPMN流程图插件,我用的是2022年的IDE,大家可以参考。

3.根据业务需求设计流程图,如下图:

图3-1项目资源目录下新建processes->xxx.bpmn20.xml文件

            图3-2 在bpmn20.xml文件中右键->选择View BPMN(Activiti)Diagram在视图中打开

 图3-3 在打开的视图中右键选择流程符号定义流程图

流程图的定义因需求和场景各有差异,对于流程的定义大家可以看看我整理的 《BPMN流程符号介绍》 ,设计好自己的业务流程

下面是我设计好的工作流流程图,用于建议征集过程的自动化办公

3.业务代码实现个人任务查询、组任务查询,任务处理,任务归还,任务拾取以及完成任务。BusinessKey应该和自己的业务主键id相关联,我这里与自己数据库中建议表的主键id相关联,所以可以由BusinessKey对建议表中数据进行查询。

控制层 

package com.yqj.imli.controller;

import com.yqj.imli.controller.Request.MotionRequest;
import com.yqj.imli.controller.Request.TaskRequest;
import com.yqj.imli.entity.Group;
import com.yqj.imli.entity.HistoryTask;
import com.yqj.imli.entity.Motion;
import com.yqj.imli.entity.Result;
import com.yqj.imli.service.impl.MyHistoryService;
import com.yqj.imli.service.impl.QueryCandidateUsersService;
import com.yqj.imli.service.impl.QueryTaskService;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
@RestController
@CrossOrigin
@RequestMapping("/task")

public class TaskController {
    //提供对流程定义和部署存储库的访问服务
   @Autowired
    HistoryService historyService;

    //运行时的接口
    @Autowired
    RuntimeService runtimeService;

    // 任务处理接口
    @Autowired
    TaskService taskService;

    @Autowired
    MyHistoryService myHistoryService;

    @Autowired
    QueryTaskService queryTaskService;

    @Autowired
    QueryCandidateUsersService queryCandidateUsersService;

    /**
     *  用户提交议案时生成流程实例, 用户完成任务
     */
    @PostMapping("/startProcess")
    public Result startProcess(@RequestBody MotionRequest motionRequest) {
        System.out.println("motionRequest: " +motionRequest);

        Map<String, Object> variablesMap = new HashMap<>();

        String ID = String.valueOf(motionRequest.getId());
        List<String> candidateUsers = queryCandidateUsersService.queryCandidateUsers(motionRequest.getAddress());
        System.out.println("candidateUsers: " +candidateUsers);
        variablesMap.put("candidateUserList", candidateUsers);
        variablesMap.put("user", motionRequest.getFrom());
        variablesMap.put("NPC", motionRequest.getTo());

        //通过流程定义ID启动一个流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myMotion", ID, variablesMap);
        log.info("流程实例:{}", processInstance);
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myMotion")
                .taskAssignee(motionRequest.getFrom())
                .singleResult();
        taskService.complete(task.getId());
        myHistoryService.saveHistoryTask(Integer.valueOf(processInstance.getBusinessKey()), task.getAssignee(), new SimpleDateFormat("YYYY年MM月dd日 HH:mm").format(new Date()), "提交待处理", null, null);
        return Result.success("议案提交成功");
    }

    /**
     *  完成个人任务
     */
    @PostMapping("/completeTask")
    public Result completeTask(@RequestBody TaskRequest taskRequest) {
        System.out.println("taskRequest: " +taskRequest);
        Task task = taskService.createTaskQuery()
                .processInstanceBusinessKey(String.valueOf(taskRequest.getId()))
                .singleResult();
        taskService.complete(task.getId());
        myHistoryService.saveHistoryTask(taskRequest.getId(), task.getAssignee(), new SimpleDateFormat("YYYY年MM月dd日 HH:mm").format(new Date()), "完成任务", taskRequest.getHandingRes() , taskRequest.getHandingOpinions());
        return Result.success("");
    }

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

    @GetMapping("/staticByAssigneeTask")
    public Result staticByAssigneeTask(String NPC) {
        Integer task = queryOwnerTask(NPC).size();

        return Result.success(task);
    }


    @GetMapping("/queryByAssigneeTask")
    public Result queryByAssigneeTask(@Param("NPC") String NPC, @Param("size") Integer size, @Param("page") Integer page) {
        System.out.println("size: " +size);
        System.out.println("page: " +page);
        List<Task> taskList = queryOwnerTask(NPC);
        if(taskList == null || taskList.size() == 0) {
            System.out.println("个人任务不存在");
            return Result.error("个人任务不存在");
        }
        List<Integer> businessKeyList = new ArrayList<>();
        for (Task task : taskList) {
//            使用task对象获取实例id
            String processInstanceId = task.getProcessInstanceId();
//            使用实例id, 获取流程实例对象
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
//            获取业务主键
            businessKeyList.add(Integer.valueOf(processInstance.getBusinessKey()));
        }

//        通过businessKey查询任务中所对应的业务内容

        List<Motion> motions = queryTaskService.queryMotionByBusinessKey(businessKeyList, size, page);
        Map<String, Object> taskMap = new HashMap<>();
        taskMap.put("number", taskList.size());
        taskMap.put("motions", motions);
        return Result.success(taskMap);
    }

    @GetMapping("/staticAssigneeTask")
    public Result staticAssigneeTask(String NPC) {
        List<Task> taskList = queryOwnerTask(NPC);
        if(taskList == null || taskList.size() == 0) {
            System.out.println("个人任务不存在");
            return Result.error("个人任务不存在");
        }
        List<Integer> businessKeyList = new ArrayList<>();
        for (Task task : taskList) {
//            使用task对象获取实例id
            String processInstanceId = task.getProcessInstanceId();
//            使用实例id, 获取流程实例对象
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
//            获取业务主键
            businessKeyList.add(Integer.valueOf(processInstance.getBusinessKey()));
        }
        List<Group> groups = queryTaskService.staticAssigneeTask(businessKeyList);
        Map<String, Object> taskMap = new HashMap<>();
        taskMap.put("number", taskList.size());
        taskMap.put("groups", groups);
        return Result.success(taskMap);
    }


    /**
     * 查询已完成任务
     */

    @GetMapping("/staticFinishedTask")
    public Result staticFinishedTask(String NPC) {
        Integer completedTask = myHistoryService.queryFinishedTask(NPC).size();
        List<Group> groups = myHistoryService.groupFinishedBySort(NPC);
        System.out.println("分组后: " +groups);
        Map<String, Object> completedTaskNumbermap = new HashMap<>();
        completedTaskNumbermap.put("completedTask", completedTask);
        completedTaskNumbermap.put("groups", groups);
        return Result.success(completedTaskNumbermap);
    }

    @GetMapping("/queryFinishedTask")
    public Result queryFinishedTask(String NPC) {
        //        查询历史任务
        List<Motion> motions = myHistoryService.queryFinishedTask(NPC);
        for (Motion motion : motions) {
            HistoryTask historyTask = myHistoryService.queryHandingMessage(motion.getMotion());
            if (historyTask != null) {
                motion.setHandingRes(historyTask.getHandingRes());
                motion.setHandingOpinion(historyTask.getHandingOpinions());
            }
        }

        return Result.success(motions);

    }

    @PutMapping("/removeFinished")
    public Result remove (@RequestBody List<TaskRequest> taskRequestList) {
        for (TaskRequest finishedTask : taskRequestList) {
            myHistoryService.remove(finishedTask.getId());
        }
        return Result.success();
    }

    /**
     *
     * @param id
     * @return
     */

    @GetMapping("/hiddenFinishedTask/{id}")
    public Result hiddenFinishedTask(@PathVariable Integer id) {
        myHistoryService.updateHistoryTask(id);
        return Result.success("");
    }


    /**
     * 查询组任务
     */

    @GetMapping("/staticGroupTask")
    public Result staticGroupTask(String NPC) {
        Integer claimableTask = taskService.createTaskQuery()
                .processDefinitionKey("myMotion")
                .taskCandidateUser(NPC)
                .list()
                .size();
        return Result.success(claimableTask);
    }

    @GetMapping("/checkGroupTask")
    public Result checkGroupTask(@Param("NPC") String NPC, @Param("size") Integer size, @Param("page") Integer page) {
//        securityUtil.logInAs(NPC);
        List<Task> tasks = taskService.createTaskQuery()
                .processDefinitionKey("myMotion")
                .taskCandidateUser(NPC)
                .list();
        if (tasks == null || tasks.size() == 0) {
            return Result.error("任务不存在");
        }
        List<Integer> businessKeyList = new ArrayList<>();
        for (Task task : tasks) {
            String processInstanceId = task.getProcessInstanceId();
//            使用实例id, 获取流程实例对象
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
//            获取业务主键
            businessKeyList.add(Integer.valueOf(processInstance.getBusinessKey()));
        }
        List<Motion> motions = queryTaskService.queryMotionByBusinessKey(businessKeyList, size, page);
        Map<String, Object> taskMap = new HashMap<>();
        taskMap.put("number", tasks.size());
        taskMap.put("motions", motions);
        return Result.success(taskMap);
    }

    @GetMapping("/claimTask")
    public Result claimTask(Integer id,String NPC) {
        Task task = taskService.createTaskQuery()
                .processInstanceBusinessKey(String.valueOf(id))
                .singleResult();
        taskService.claim(task.getId(), NPC);
        myHistoryService.saveHistoryTask(id, NPC, new SimpleDateFormat("YYYY年MM月dd日 HH:mm").format(new Date()), "拾取任务", null , null);
        return Result.success("任务拾取成功");
    }

    /**
    *  归还任务
     */
    @GetMapping("/{id}")
    public Result returnTask(@PathVariable Integer id) {
        Task task = taskService.createTaskQuery()
                .processInstanceBusinessKey(String.valueOf(id))
                .singleResult();
        taskService.claim(task.getId(), null);
        myHistoryService.saveHistoryTask(id, task.getAssignee(), new SimpleDateFormat("YYYY年MM月dd日 HH:mm").format(new Date()), "归还任务", null , null);
        return Result.success("归还任务成功");
    }

    @GetMapping("/queryHistoryTask/{comment}")
    public Result queryHistoryTask (@PathVariable Integer comment) {
        List<HistoryTask> historyTasks = myHistoryService.queryHistoryTask(comment);
        return Result.success(historyTasks);
    }

   public  List<Task> queryOwnerTask(String NPC) {
       List<Task> taskList = taskService.createTaskQuery()
               //代办人姓名
               .taskAssignee(NPC)
               //活动状态
               .active()
               .list();
       return taskList;
   }
}

业务层     MyHistoryService.Java用于记录建议的所有状态,以便流程公开透明。具体代码根据自己的真实需求和数据库表设计编写,也可以没有。其他业务层方法由Activiti7相关jar包直接导入(不用编写,导入Maven依赖后可用)。

package com.yqj.imli.service.impl;


import com.yqj.imli.entity.Group;
import com.yqj.imli.entity.HistoryTask;
import com.yqj.imli.entity.Motion;
import com.yqj.imli.mapper.MyHistoryMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service("historyService")
public class MyHistoryService {

    @Autowired
    MyHistoryMapper myHistoryMapper;



    public void saveHistoryTask(Integer id, String assignee, String time, String activityName, String handingRes, String handingOpinions) {
        myHistoryMapper.saveHistoryTask(id, assignee, time, activityName, handingRes, handingOpinions);

    }

    public List<HistoryTask> queryHistoryTask(Integer comment) {
        List<HistoryTask> historyTasks = myHistoryMapper.queryHistoryTask(comment);
        return historyTasks;
    }

    public List<Motion> queryFinishedTask(String NPC) {
        List<Motion> motions = myHistoryMapper.queryFinishedTask(NPC);
        return motions;
    }

    public List<Group> groupFinishedBySort(String NPC) {
        List<Group> groups = myHistoryMapper.groupFinishedBySort(NPC);
        return groups;
    }

    public HistoryTask queryHandingMessage(Integer id) {
        HistoryTask historyTask = myHistoryMapper.queryHandingMessage(id);
        return historyTask;
    }

    public void updateHistoryTask(Integer id) {
        myHistoryMapper.updateHistoryTask(id);
    }

    public void remove(Integer id) {
        myHistoryMapper.remove(id);
    }
}

Mapper层

package com.yqj.imli.mapper;

import com.yqj.imli.entity.Group;
import com.yqj.imli.entity.HistoryTask;
import com.yqj.imli.entity.Motion;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface MyHistoryMapper {
    void saveHistoryTask(@Param("id") Integer id, @Param("assignee") String assignee, @Param("time") String time, @Param("activityName") String activityName,@Param("handingRes") String handingRes, @Param("handingOpinions") String handingOpinions);

    List<HistoryTask> queryHistoryTask(@Param("id") Integer id);

    List<Motion> queryFinishedTask(@Param("NPC") String NPC);

    List<Group> groupFinishedBySort(@Param("NPC") String NPC);

    HistoryTask queryHandingMessage(@Param("id") Integer id);

    void updateHistoryTask(@Param("motionId") Integer motionId);

    void remove(@Param("id") Integer id);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yqj.imli.mapper.MyHistoryMapper">


    <insert id="saveHistoryTask">
        insert into history_task (MOTION_ID, assignee, activity_name, time, handing_res, handing_opinions, `show`)
            VALUES (#{id}, #{assignee}, #{activityName}, #{time}, #{handingRes}, #{handingOpinions}, 1)
    </insert>

    <update id="updateHistoryTask">
        update history_task
            set `show` = 0
                where MOTION_ID = #{motionId}
    </update>
    <update id="remove">
        update history_task
            set `show` = 0
                where MOTION_ID = #{id}
    </update>

    <select id="queryHistoryTask" resultType="com.yqj.imli.entity.HistoryTask">
        select id, assignee, activity_name, time, handing_res, handing_opinions
            from history_task
            <where>
                <if test="id != null and id!= ''">
                    MOTION_ID = #{id}
                </if>
            </where>
                order by
                    unix_timestamp(time) asc
    </select>

    <select id="queryFinishedTask" resultType="com.yqj.imli.entity.Motion">
        select * from motion
            where id in (select MOTION_ID from history_task
                                         where assignee = #{NPC}
                                           and activity_name = '完成任务' and `show` = 1)
    </select>

    <select id="groupFinishedBySort" resultType="com.yqj.imli.entity.Group">
        select sort, count(id) as num from motion
            where id in (select MOTION_ID from history_task
                                             where assignee = #{NPC}
                                                and activity_name = '完成任务' and `show` = 1)
                             group by
                                            sort
    </select>

    <select id="queryHandingMessage" resultType="com.yqj.imli.entity.HistoryTask">
        select handing_res , handing_opinions from history_task
            where
                MOTION_ID = #{id}
                    and
                        activity_name = '完成任务'
    </select>
</mapper>

在启动过程中如果遇到下面的报错,在数据库中添加缺少的字段就可以了。

以上就是我开发的所有过程了,谢谢大家的阅读,希望能够对大家有所帮助。 

标签:task,springboot,NPC,String,Activiti7,OA,import,id,Result
From: https://blog.csdn.net/weixin_74758471/article/details/139859840

相关文章

  • springboot 前后端大打包成一个JAR
    1.概述现在开发使用前后端开发机制,在部署的时候,我们需要将前后端分别打包,使用nginx进行统一部署。这样就比较复杂,我们可以使用前后端打包到一个jar中,这样我们只需要一个包就可以了。2.实现我们只需要将前端的编译好的文件,在打包时,将前端文件copy到resources目录下的stat......
  • Dragon Boat Festival Revised
    Asweallknow,theDragonBoatFestivalholdsprofoundhistoricalandculturalsignificance.TheDragonBoatFestivalwasoriginallyasummerfestivaltogetridofplague,andlateritwasusedasafestivalinmemoryofQuYuan.Dragonboatracingsymb......
  • SpringBoot 项目启动后监听器执行操作:ContextRefreshEvent
    一Springboot运行时,会依次发送以下事件1. ApplicationStartingEvent 2. ApplicationEnvironmentPreparedEvent:当Environment已经准备好,在context创建前3. ApplicationContextInitializedEvent:在ApplicationContext创建和ApplicationContextInitializer都被调用后,但是......
  • 在使用InputStream templateStream = this.getClass().getClassLoader().getResourceA
    在使用 this.getClass().getClassLoader().getResourceAsStream()读取项目目录路径下的文件需要注意在pom.xml文件中加入<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-......
  • 基于springboot地方废物回收机构管理系统
    收藏关注不迷路||项目不适合可以浏览博主其他项目文章项目源码||毕设定制||远程支持||可联系博主---------------同类型文章链接--------------------------java项目设计专栏1项目基于springboot地方废物回收机构管理系统本系统的核心价值观在于为用户打造一个便......
  • flutter Warning: CocoaPods is installed but broken. Skipping pod install. You
    flutterWarning:CocoaPodsisinstalledbutbroken.Skippingpodinstall.YouappeartohaveCocoaPodsins确保你已经安装了CocoaPods并可以正常使用:1.flutterclean2.flutterpubget3.cdios4.podinstall5.退出vscode,并重新打开6.再次运行项目运行后如果......
  • 计算机Java项目|SpringBoot在线宠物用品交易网站
    作者主页:编程指南针作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互......
  • Dragon Boat Festival Revised
    Thefestival,acommemorationoftheesteemedancientChinesepoetQuYuan,traditionallymarksatimeforfamilialreunions,thethrillingdragonboatraces,andtheindulgenceintraditionaldelicaciessuchaszongzi.However,thisyear,duetomystudi......
  • Springboot+Vue+Mybatis-Plus+Easyexcel实现文件导入+导出的excel单元格下拉列表
    引言文件的导入与导出功能扮演着至关重要的角色,特别是在处理大量数据和复杂的表格时。通过整合SpringBoot、Vue、Mybatis-Plus和Easyexcel等先进技术,我们可以构建一个高效、灵活的文件处理系统。其中,Excel作为广泛使用的电子表格软件,其单元格下拉列表功能对于数据录入和校验......
  • ThingsBoard实现告警规则创建并生成报警信息
    一、概述1.概念2.告警规则3.简单报警条件步骤1.打开设置配置​步骤2.单击警报规则​步骤3.单击警报条件​步骤4.单击过滤条件步骤5.选择数据键​步骤6.设置条件​步骤7.保存条件步骤8.应用更改4.测试告警 1、使用MQTT发送遥测属性 2、查看告警列表,已存......