云尚办公项目学习

完整的笔记可以参考这个专栏,写的挺详细的:云尚办公课件笔记,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.mzph.cn/news/600377.shtml

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

相关文章

移动零【双指针】

Problem: 283. 移动零 文章目录 思路 & 解题方法复杂度Code 思路 & 解题方法 使用双指针&#xff0c;左指针指向当前已经处理好的序列的尾部&#xff0c;右指针指向待处理序列的头部。 右指针不断向右移动&#xff0c;每次右指针指向非零数&#xff0c;则将左右指针对应…

VuePress部署到GitHub Pages

一、git push自动部署 1、创建用于工作流的文件 在项目根目录下创建一个用于 GitHub Actions 的工作流 .yml 文件 name: docson:# 每当 push 到 main 分支时触发部署push:branches: [main]# 手动触发部署workflow_dispatch:jobs:docs:runs-on: ubuntu-lateststeps:- uses: a…

深入Pandas:数据分析的强大工具

文章目录 引言Pandas简介Pandas的核心功能实战示例&#xff1a;数据分析与可视化示例目的环境需求示例数据集示例过程及结果源代码 结语 引言 在当今快速发展的数据科学领域&#xff0c;Python凭借其强大的库生态系统&#xff0c;特别是像Pandas这样的库&#xff0c;已成为数据…

MACOS Atrust服务异常

MAC版Atrust服务异常 点击进入办公后出现提示其一&#xff1a; 核心服务未启动&#xff0c;部分功能存在异常&#xff0c;确定重新启动吗&#xff1f; 可能的原因&#xff1a; 1.上次已完全退出客户端 2.核心服务被其他程序优化禁用 点击重新启动后&#xff0c;出现提示&#x…

【React】react-router-dom中的HashRouter和BrowserRouter实现原理

1. 前言 在之前整理BOM的五个对象时&#xff0c;提到&#xff1a; location.hash发生改变后&#xff0c;会触发hashchange事件&#xff0c;且history栈中会增加一条记录&#xff0c;但页面不会重新加载——实现HashRouter的关键history.pushState(state, , URL)执行后&#xf…

Chinese-llama-2部署踩坑记录

Chinese-llama-2部署踩坑记录 1. Chinese-LLaMA-Alpaca-2A. 部署a. inference_with_transformers_zhb. text generation webui_zhc. api_calls_zhd. llamacpp_zhe. privategpt_zhf. langchain_zh Tool Github 1. Chinese-LLaMA-Alpaca-2 A. 部署 a. inference_with_transform…

新手深入PyTorch中RNN、LSTM和GRU使用和理解

目录 torch.nn子模块Recurrent Layers nn.RNNBase RNNBase 类描述 RNNBase 类的功能和作用 flatten_parameters() 方法 示例代码 nn.RNN RNN 类描述 RNN 类的功能和作用 RNN 类的参数 输入和输出 注意事项 示例代码 nn.LSTM LSTM 类描述 LSTM 类的功能和作用 …

05、Kafka ------ CMAK 各个功能的作用解释(主题和分区 详解,用命令行和图形界面创建主题和查看主题)

目录 CMAK 各个功能的作用解释&#xff08;主题&#xff09;★ 主题★ 分区★ 创建主题&#xff1a;★ 列出和查看主题 CMAK 各个功能的作用解释&#xff08;主题&#xff09; ★ 主题 Kafka 主题虽然也叫 topic&#xff0c;但它和 Pub-Sub 消息模型中 topic 主题及 AMQP 的 t…

【AI视野·今日NLP 自然语言处理论文速览 第六十六期】Tue, 31 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Tue, 31 Oct 2023 (showing first 100 of 141 entries) Totally 100 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers The Eval4NLP 2023 Shared Task on Prompting Large Language Models a…

nginx下日志配置和排查错误

目录 一&#xff1a;配置 二&#xff1a;排查日志 一&#xff1a;配置 在Nginx中&#xff0c;日志配置是记录服务器活动和排查问题的重要环节。以下是一些常见的Nginx日志配置选项&#xff1a; 日志级别&#xff1a;通过设置日志级别&#xff0c;可以控制日志的详细程度。常…

【心得杂记】简单聊聊限制高速面阵相机性能的因素

研究了限制高速面阵相机发展的因素&#xff0c;感觉就是揭开了薄雾面纱之后的复杂。 个人观点&#xff0c;不保证全对~ 欢迎讨论~ 高速相机是一个整体&#xff0c;涉及的各个零部件和模组很多&#xff0c;每个环节都会影响相机指标的提高。 高速相机主要包括的核心部件有&#…

什么是低代码开发平台(Low Code Platform) 有什么优势特点

低代码平台(Low Code Platform)是一种用于快速开发应用程序的软件开发平台。它通过可视化的界面和简化的开发工具&#xff0c;使开发人员能够使用少量的编码和配置来构建复杂的应用程序。 白码低代码平台是一种高效、灵活的软件开发工具&#xff0c;通过可视化的界面和少量的编…

vue3(十二)-基础入门之反向代理

一、反向代理 当遇到跨域问题时&#xff0c;可以通过反向代理解决跨域问题 1、创建一个与 package.json 同级的文件 vue.config.js vue.config.js &#xff1a; 代理以 /ajax 为开头的地址。代理服务器为 &#xff1a;https://www.xxxx.com const { defineConfig } requi…

普中STM32-PZ6806L开发板(HAL库函数实现-按键扫描)

简介 实现按键扫描, 实现四个按键按下控制灯的亮灭 电路原理图 按键电路原理图 按键与主芯片引脚原理图 其他知识 原理图分析 Key_UP按下会有高电平输入, 所以电路设置应该是默认低电平, 初始化为下拉输入 Key_Left/Right/Down按下会有低电平&#xff0c; 初始化为下拉输…

OpenHarmony从入门到放弃(四)

设计一款使用Harmony开发的App 接下来我会通过设计并开发一款资讯类的App来入门OpenHarmony&#xff1b; 以下是我对App的设计想法&#xff1b; 一、模块划分 内容模块&#xff1a;App的核心模块&#xff0c;负责管理和展示资讯内容&#xff0c;具体包括内容获取与处理&…

Winform、WPF如何解决前端卡死问题

在WinForms和WPF中&#xff0c;前端卡死问题通常是由于长时间的计算或阻塞操作导致的。以下是一些解决前端卡死问题的常见方法&#xff1a; 使用异步操作&#xff1a;将长时间的计算或阻塞操作放在后台线程中执行&#xff0c;以避免阻塞UI线程。可以使用Task、async/await等异步…

CSS 使用技巧

CSS 使用技巧 引入苹方字体 苹方提供了六个字重&#xff0c;font-family 定义如下&#xff1a;苹方-简 常规体font-family: PingFangSC-Regular, sans-serif;苹方-简 极细体font-family: PingFangSC-Ultralight, sans-serif;苹方-简 细体font-family: PingFangSC-Light, sans…

uniapp vue2 车牌号输入组件记录

uniapp vue2 车牌号输入案例记录 组件如图 直接上代码 1.html <template><view><view class"plate" :class"{show: show}"><view class"itemFirst flex-d"><view class"item item1" click"handl…

Ubuntu不能挂载移动硬盘

我有一个2T 的移动硬盘&#xff0c;分了两个区 不知道为啥突然之间一个分区老无法挂载&#xff0c;万能的重启也无法解决。 经查资料&#xff0c;这种情况一般是在使用时&#xff08;如看电影或者拷贝文件过程中&#xff09;将移动硬盘异常拔出再插入时&#xff0c;就提示不能…

学习录

概述 这几年在迷茫中看了不少资料&#xff0c;有觉得写得很棒的&#xff0c;也有写的很糟糕的。所以一直想写这块的总结来进行归纳&#xff0c;同时也希望能给其他处于迷茫中的朋友提供一份高质量的资料列表(也许一个读者也没有)&#xff0c;以下清单个人觉得值得反复看以及思…