云尚办公项目学习

完整的笔记可以参考这个专栏,写的挺详细的:云尚办公课件笔记,come on boy

form-create前端组件
formProps记录了表单有哪些表单项,分别是哪些类型(下拉,单选,输入框)
formOptions记录了表单的一些配置项,比如label-width等

在这里插入图片描述
mybatisplus生成代码

oa_process_type 审批类型
oa_process_template 审批模板

oa_prcess 审批列表(关联审批流流程实例id)

1,创建审批类型
2,创建审批类型下的审批模板
3,为指定的审批模板设置模板名称,表单项,
4,为指定的审批模板上传流程定义文件,将该文件保存到指定的目录下,并保存到审批模板的流程定义path字段,流程定义文件的文件名(不包括后缀名)作为审批模板的流程定义key字段
5,发布该审批模板,就是将此审批模板流程定义path字段所指定的路径所对应的文件读取成流,部署到activiti中,修改审批模板为已发布状态

6,发起审批,首先获取审批模板对应的表单,申请人填写表单内容,表单内容会转换为json数据传给后台,后台根据审批模板将数据保存到业务审批表,申请人填写的表单内容就保存在业务审批表的form_values字段中,这样就可以得到业务id了,然后activiti使用审批模板所保存的流程定义key启动流程实例,并传入业务id,同时传入将申请人填写的表单内容json数据转为的map存入到key为data的map中,这样流程实例就启动了,并且和业务id绑定了,并且也有了申请人填写的表单内容作为流程变量。

在流程实例启动后,立即查询当前流程实例的下一个节点的审批人(有可能有多个),取到这些审批人的assignee,给这些审批人推送消息以便于提醒他们尽快去审批。

推送完消息之后,将流程实例id保存到业务审批表的流程实例id字段。

//启动流程
@Override
public void startUp(ProcessFormVo processFormVo) {//1 根据当前用户id获取用户信息SysUser sysUser = sysUserService.getById(LoginUserInfoHelper.getUserId());//2 根据审批模板id把模板信息查询ProcessTemplate processTemplate = processTemplateService.getById(processFormVo.getProcessTemplateId());//3 保存提交审批信息到业务表,oa_processProcess process = new Process();//processFormVo复制到process对象里面BeanUtils.copyProperties(processFormVo,process);//其他值process.setStatus(1); //审批中String workNo = System.currentTimeMillis() + "";process.setProcessCode(workNo);process.setUserId(LoginUserInfoHelper.getUserId());process.setFormValues(processFormVo.getFormValues());process.setTitle(sysUser.getName() + "发起" + processTemplate.getName() + "申请");baseMapper.insert(process);//4 启动流程实例 - RuntimeService//4.1 流程定义keyString processDefinitionKey = processTemplate.getProcessDefinitionKey();//4.2 业务key  processIdString businessKey = String.valueOf(process.getId());//4.3 流程参数 form表单json数据,转换map集合String formValues = processFormVo.getFormValues();//formDataJSONObject jsonObject = JSON.parseObject(formValues);JSONObject formData = jsonObject.getJSONObject("formData");//遍历formData得到内容,封装map集合Map<String,Object> map = new HashMap<>();for(Map.Entry<String,Object> entry:formData.entrySet()) {map.put(entry.getKey(),entry.getValue());}Map<String,Object> variables = new HashMap<>();variables.put("data",map);//启动流程实例ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,businessKey, variables);//5 查询下一个审批人//审批人可能多个List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();List<String> nameList = new ArrayList<>();for(Task task : taskList) {String assigneeName = task.getAssignee();SysUser user = sysUserService.getUserByUserName(assigneeName);String name = user.getName();nameList.add(name);//推送消息messageService.pushPendingMessage(process.getId(),user.getId(),task.getId());}process.setProcessInstanceId(processInstance.getId());process.setDescription("等待"+ StringUtils.join(nameList.toArray(), ",")+"审批");//7 业务和流程关联  更新oa_process数据baseMapper.updateById(process);//记录操作审批信息记录processRecordService.record(process.getId(),1,"发起申请");
}

7、审批记录
用来记录1个审批所走过的轨迹,首先添加审批记录表,如下
在这里插入图片描述
在开启流程实例的方法中,生成一条审批记录存入到审批记录表当中(调用处在上面)

@Override
public void record(Long processId, Integer status, String description) {Long userId = LoginUserInfoHelper.getUserId();SysUser sysUser = sysUserService.getById(userId);ProcessRecord processRecord = new ProcessRecord();processRecord.setProcessId(processId);processRecord.setStatus(status);processRecord.setDescription(description);processRecord.setOperateUser(sysUser.getName());processRecord.setOperateUserId(userId);baseMapper.insert(processRecord);
}

8,审批人查询待办任务

使用activiti工作流提供的taskService根据当前用户作为assignee查询当前用户的的任务列表(并且使用了分页),遍历这个任务列表,可以拿到每个任务对应的流程实例,然后拿到流程实例对应的业务key(其实,通过task就可以直接拿到businessKey),拿到businessKey之后,就可以查询业务审批表,来获取到申请人所填写的申请表单内容了。这样当前审批人就可以根据申请人提交的表单内容做审批了。注意,工作流的taskId也带上去了。

//查询待处理任务列表
@Overridepublic IPage<ProcessVo> findfindPending(Page<Process> pageParam) {//1 封装查询条件,根据当前登录的用户名称TaskQuery query = taskService.createTaskQuery().taskAssignee(LoginUserInfoHelper.getUsername()).orderByTaskCreateTime().desc();//2 调用方法分页条件查询,返回list集合,待办任务集合//listPage方法有两个参数//第一个参数:开始位置  第二个参数:每页显示记录数int begin = (int)((pageParam.getCurrent()-1)*pageParam.getSize());int size = (int)pageParam.getSize();List<Task> taskList = query.listPage(begin, size);long totalCount = query.count();//3 封装返回list集合数据 到 List<ProcessVo>里面//List<Task> -- List<ProcessVo>List<ProcessVo> processVoList = new ArrayList<>();for(Task task : taskList) {//从task获取流程实例idString processInstanceId = task.getProcessInstanceId();//根据流程实例id获取实例对象ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();//从流程实例对象获取业务key---processIdString businessKey = processInstance.getBusinessKey();if(businessKey == null) {continue;}//根据业务key获取Process对象long processId = Long.parseLong(businessKey);Process process = baseMapper.selectById(processId);//Process对象 复制 ProcessVo对象ProcessVo processVo = new ProcessVo();BeanUtils.copyProperties(process,processVo);processVo.setTaskId(task.getId());//放到最终list集合processVoListprocessVoList.add(processVo);}//4 封装返回IPage对象IPage<ProcessVo> page = new Page<ProcessVo>(pageParam.getCurrent(),pageParam.getSize(),totalCount);page.setRecords(processVoList);return page;}

9,发起审批测试
测试步骤如下,

先添加审批模板,然后发布,使用admin填写审批表单发起1个审批,然后下一节点审批人zhangsan查看自己的待办任务
在这里插入图片描述
张三查看自己的待办任务列表如下
在这里插入图片描述
10,审批人查看审批单的审批详情信息

前面张三查看到了自己的待办任务列表,待办任务列表数据的id是业务表的id,因此前端将此id传进来,来查询审批详情信息(比如用户什么时间提的申请,填写的表单内容)。

接着,继续使用业务表的id查询审批记录表中的审批记录(前面发起审批时,记录了,当前自己审批时,也须往这个表中记录)

接着,根据审批业务表的id得到审批模板信息

接着,查询当前人是否可以审批该审批流程实例(这里要推敲下)

下面这个代码感觉有点问题:上面查询待办的时候,拿的就是当前人作为assignee查询的任务,那么查到的审批单对应的审批人是一定包括当前人的(可能有多个审批人),并且,也是有查询到对应的taskId的,我觉得这里应该让前端把taskId传过来,就可以得到这个taskId对应的assignee是不是当前人。但是好好想想,他这样做也没啥问题,他其实就是在判断当前人是否是这个流程实例的当前所在节点的审批人,如果是的话,那就可以审批,不是的话,就不可以审批

//查看审批详情信息
@Override
public Map<String, Object> show(Long id) {//1 根据流程id获取流程信息ProcessProcess process = baseMapper.selectById(id);//2 根据流程id获取流程记录信息LambdaQueryWrapper<ProcessRecord> wrapper = new LambdaQueryWrapper<>();wrapper.eq(ProcessRecord::getProcessId,id);List<ProcessRecord> processRecordList = processRecordService.list(wrapper);//3 根据模板id查询模板信息ProcessTemplate processTemplate = processTemplateService.getById(process.getProcessTemplateId());//4 判断当前用户是否可以审批//可以看到信息不一定能审批,不能重复审批boolean isApprove = false;List<Task> taskList = this.getCurrentTaskList(process.getProcessInstanceId());for(Task task : taskList) {//判断任务审批人是否是当前用户String username = LoginUserInfoHelper.getUsername();if(task.getAssignee().equals(username)) {isApprove = true;}}//5 查询数据封装到map集合,返回Map<String,Object> map = new HashMap<>();map.put("process", process);map.put("processRecordList", processRecordList);map.put("processTemplate", processTemplate);map.put("isApprove", isApprove);return map;
}

张三点击审批详情后,进入到如下页面

在这里插入图片描述
11,最重要的一步来了,审批人对当前审批单进行审批(同意or驳回)。驳回即审批不通过,流程结束。
如果当前审批人 对 此审批单 审批通过,那么流程引擎会自动将任务流转到下1个审批人那里(如果还有下一个任务节点的话),并通知下一个审批人(可能是多个人),下一个人就可以查询到自己的待办任务。

如果当前审批人 对 此审批单 驳回,那么流程结束。结束流程的代码是固定模式的。

不管当前审批人 对 此审批单 是审批通过 还是驳回,都要记录到审批记录表,并且更新审批的业务表。

//审批
@Override
public void approve(ApprovalVo approvalVo) {//1 从approvalVo获取任务id,根据任务id获取流程变量String taskId = approvalVo.getTaskId();Map<String, Object> variables = taskService.getVariables(taskId);for(Map.Entry<String,Object> entry:variables.entrySet()) {System.out.println(entry.getKey());System.out.println(entry.getValue());}//2 判断审批状态值if(approvalVo.getStatus() == 1) {//2.1 状态值 =1  审批通过Map<String, Object> variable = new HashMap<>();taskService.complete(taskId,variable);} else {//2.2 状态值 = -1 驳回,流程直接结束this.endTask(taskId);}//3 记录审批相关过程信息 oa_process_recordString description = approvalVo.getStatus().intValue() ==1 ? "已通过" : "驳回";processRecordService.record(approvalVo.getProcessId(),approvalVo.getStatus(),description);//4 查询下一个审批人,更新流程表记录 process表记录Process process = baseMapper.selectById(approvalVo.getProcessId());//查询任务List<Task> taskList = this.getCurrentTaskList(process.getProcessInstanceId());if(!CollectionUtils.isEmpty(taskList)) {List<String> assignList = new ArrayList<>();for(Task task : taskList) {String assignee = task.getAssignee();SysUser sysUser = sysUserService.getUserByUserName(assignee);assignList.add(sysUser.getName());//TODO 公众号消息推送}//更新process流程信息process.setDescription("等待" + StringUtils.join(assignList.toArray(), ",") + "审批");process.setStatus(1);} else {if(approvalVo.getStatus().intValue() == 1) {process.setDescription("审批完成(通过)");process.setStatus(2);} else {process.setDescription("审批完成(驳回)");process.setStatus(-1);}}baseMapper.updateById(process);
}
//结束流程
private void endTask(String taskId) {//1 根据任务id获取任务对象 TaskTask task = taskService.createTaskQuery().taskId(taskId).singleResult();//2 获取流程定义模型 BpmnModelBpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());//3 获取结束流向节点List<EndEvent> endEventList = bpmnModel.getMainProcess().findFlowElementsOfType(EndEvent.class);if(CollectionUtils.isEmpty(endEventList)) {return;}FlowNode endFlowNode = (FlowNode)endEventList.get(0);//4 当前流向节点FlowNode currentFlowNode = (FlowNode)bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());//  临时保存当前活动的原始方向List originalSequenceFlowList = new ArrayList<>();originalSequenceFlowList.addAll(currentFlowNode.getOutgoingFlows());//5 清理当前流动方向currentFlowNode.getOutgoingFlows().clear();//6 创建新流向SequenceFlow newSequenceFlow = new SequenceFlow();newSequenceFlow.setId("newSequenceFlow");newSequenceFlow.setSourceFlowElement(currentFlowNode);newSequenceFlow.setTargetFlowElement(endFlowNode);//7 当前节点指向新方向List newSequenceFlowList = new ArrayList();newSequenceFlowList.add(newSequenceFlow);currentFlowNode.setOutgoingFlows(newSequenceFlowList);//8 完成当前任务taskService.complete(task.getId());
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/230986.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# OpenCvSharp DNN FreeYOLO 目标检测

目录 效果 模型信息 项目 代码 下载 C# OpenCvSharp DNN FreeYOLO 目标检测 效果 模型信息 Inputs ------------------------- name&#xff1a;input tensor&#xff1a;Float[1, 3, 192, 320] --------------------------------------------------------------- Outp…

NSSCTF 简单包含

开启环境: 使用POST传flag&#xff0c;flag目录/var/www/html/flag.php 先使用post来尝试读取该flag.php 没反应: 查看一下源码index.php&#xff0c;看有什么条件 base64解密: <?php$path $_POST["flag"];if (strlen(file_get_contents(php://input)) <…

vue3-12

需求是用户如果登录了&#xff0c;可以访问主页&#xff0c;如果没有登录&#xff0c;则不能访问主页&#xff0c;随后跳转到登录界面&#xff0c;让用户登录 实现思路&#xff0c;在用户登录之前做一个检查&#xff0c;如果登录了&#xff0c;则token是存在的&#xff0c;则放…

小样本学习介绍(超详细)

小样本学习介绍 本文首先介绍了什么是小样本学习&#xff0c;其次介绍了为什么小样本学习的很多文章都采用元学习的方法。目的是通过通俗的解释更加清楚的介绍小样本学习是什么&#xff0c;适合初学者的入门。当然&#xff0c;以下更多的是自己的思考&#xff0c;欢迎交流。 …

【CISSP学习笔记】6. 安全开发

该知识领域涉及如下考点&#xff0c;具体内容分布于如下各个子章节&#xff1a; 理解安全并将其融入软件开发生命周期 (SDLC) 中在软件开发环境中识别和应用安全控制评估软件安全的有效性评估获得软件对安全的影响定义并应用安全编码准则和标准 6.1. 系统开发控制 6.1.1. 软…

Python 标准库中的 csv 包

0. Abstract 官方文档很罗嗦&#xff0c;长篇大论例子少。本文将举例说明 csv 包的用法&#xff0c;然后补充一些必要的说明。 1.0 CSV 文件 CSV(Comma-Separated Values,逗号分隔值)文件是一种常见的以纯文本形式存储数据的文件格式。它使用逗号作为字段之间的分隔符&#…

关于目标检测任务中,XML(voc格式)标注文件的可视化

1. 前言 最近在弄关于目标检测的任务&#xff0c;因为检测的图片和标签是分开的&#xff0c;可视化效果不明显&#xff0c;也不知道随便下载的数据集&#xff0c;标注信息对不对。网上看了好多代码&#xff0c;代码风格和本人平时不同&#xff0c;看起来麻烦&#xff0c;也不知…

C#:如何产生一个临时文件

在我们实际编程中&#xff0c;经常有将内容写到一个临时文件的需要。 比如&#xff1a;将网络上的图片下载下来&#xff0c;获取到图片的一些信息。 代码如下&#xff0c;看结果可知&#xff1a; 临时文件都是保存在系统临时文件夹的目录下&#xff0c;临时文件的扩展名统一…

计算机毕业设计 基于Java的供应商管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

Java重修第二天—学习”方法“

通过学习本篇文章可以掌握如下知识 1、方法的定义 2、方法在计算机中的执行流程。 3、方法使用时常见问题 4、Java中方法的参数传递机制 5、方法重载 1 方法是什么 方法是一种语法结构&#xff0c;它可以把一段代码实现的某种功能封装起来&#xff0c;以便重复利用。 方…

代码+视频,手把手教你R语言使用forestploter包绘制单组及双组森林图

森林图在论文中很常见&#xff0c;多用于表示多因素分析中的变量与结果变量的比值效应&#xff0c;可以用图示的方法比较直观的绘制出来。既往我们在文章《R语言快速绘制多因素回归分析森林图&#xff08;1&#xff09;》已经介绍了怎么绘制森林图&#xff0c;但是绘图比较简单…

​电脑技巧:​笔记本电脑电流声的原因和解决方案

目录 一、音频设备接口接触不良 二、笔记本电源问题 三、笔记本电脑驱动程序问题 四、音频硬件问题 五、操作系统内部电磁干扰 六、最后总结 大家在日常生活当中&#xff0c;笔记本电脑已经成为我们工作、学习和娱乐的重要工具。但有时我们在使用过程中可能会遇到一个令人…

git回滚操作,常用场景

文章目录 git回滚操作1.git reset --hard 【版本号】2.回滚后的版本v2又想回到之前的版本v32.1 git reflog 3.git checkout -- 文件名4.git reset HEAD 文件名 git回滚操作 假设我们现在有三个版本 现在回滚一个版本 1.git reset --hard 【版本号】 发现只剩下两个版本了 2.…

git在本地创建dev分支并和远程的dev分支关联起来

文章目录 git在本地创建dev分支并和远程的dev分支关联起来1. 使用git命令2. 使用idea2.1 先删除上面建的本地分支dev2.2 通过idea建dev分支并和远程dev分支关联 3. 查看本地分支和远程分支的关系 git在本地创建dev分支并和远程的dev分支关联起来 1. 使用git命令 git checkout…

Spring Boot 3 集成 Thymeleaf

在现代的Web开发中&#xff0c;构建灵活、动态的用户界面是至关重要的。Spring Boot和Thymeleaf的结合为开发者提供了一种简单而强大的方式来创建动态的Web应用。本文将介绍如何在Spring Boot项目中集成Thymeleaf&#xff0c;并展示一些基本的使用方法。 什么是Thymeleaf&#…

2.HDFS 架构

目录 概述架构HDFS副本HDFS数据写入流程NN 工作原理DN 工作原理 结束 概述 官方文档快递 环境&#xff1a;hadoop 版本 3.3.6 相关文章速递 架构 HDFS HDFS 架构总结如下&#xff1a; a master/slave architecture 一主多从架构a file is split into one or more blocks a…

SylixOS各阶段代号说明

SylixOS已经历了多年更新迭代&#xff0c;每个阶段都会新增或完善一个重要领域&#xff0c;并命名一个代号&#xff0c;以表祝愿和纪念。

工具网站DefiLlama全攻略:从零学习链上数据使用与发现

DefiLlama 是一个 DeFi(去中心化金融)信息聚合器,其主要功能是提供各种 DeFi 平台的准确、全面数据。DefiLlama 致力于在不受广告或赞助内容影响的情况下为用户提供这些数据,以确保信息内容的透明度和公正性,该平台聚合来自多个区块链的数据,让用户能够全面了解 DeFi 格局…

全球海洋数据 (GLODAP) v2.2023(海洋碳数据产品)

全球海洋数据分析项目 (GLODAP) v2.2023 全球海洋数据分析项目 (GLODAP) v2.2023 代表了海洋生物地球化学瓶数据合成方面的重大进步。此更新主要关注海水无机碳化学&#xff0c;以 GLODAPv2.2022 为基础&#xff0c;包含多项关键增强功能。值得注意的是&#xff0c;增加了 43 …

大数据StarRocks(三) StarRocks数据表设计

1. 列式存储 1.1 列式存储方式有以下几个优点&#xff1a; 1.快速的数据查询 由于数据是按照列进行存储的&#xff0c;所以查询某个列时只需要读取该列所在的块&#xff0c;而不是整行数据&#xff0c;从而大大提高了查询效率。 2.压缩效率高 由于列式存储的数据块中只有一…