15.Activiti7
部署-启动-分配-拾取-完成-(转交-完成)-结束 途中可以查询
/**
* @author Yangmc email:yangmc@tayo.com
* @create 2024-01-26 6:35
* @description 请假审批流程
*/
@SpringBootTest
public class ProcessTest {
@Autowired
private RepositoryService repositoryService;//部署流程定义,管理流程资源
@Autowired
private RuntimeService runtimeService;//启动流程实例
@Autowired
private TaskService taskService;//处理业务运行中的各种任务
@Autowired
private HistoryService historyService;//查询历史信息
/**
* 单个文件的部署
*/
@Test
public void deployProcess() {
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("process/qingjia.bpmn20.xml")//加载类路径下的资源
.addClasspathResource("process/qingjia.png")
.name("请假申请流程")
.deploy();
System.out.println("流程id:" + deploy.getId());
System.out.println("流程名称:" + deploy.getName());
}
/**
* 启动流程实例
*/
@Test
public void startProcess() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("qingjia");
System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
System.out.println("流程实例id:" + processInstance.getId());
System.out.println("当前活动id:" + processInstance.getActivityId());
}
/**
* 查询个人的代办任务--zhangsan
*/
@Test
public void findTaskList() {
String assign = "zhangsan";
List<Task> list = taskService.createTaskQuery()
.taskAssignee(assign)
.list();
for (Task task : list) {
System.out.println("流程实例id" + task.getProcessInstanceId());
System.out.println("任务id:" + task.getId());
System.out.println("任务负责人:" + task.getAssignee());
System.out.println("任务名称:" + task.getName());
}
}
/**
* 处理当前任务
*/
@Test
public void completeTask() {
// 查询负责人需要处理的任务,返回一条
Task task = taskService.createTaskQuery().
taskAssignee("zhangsan").
singleResult();
// 完成任务.参数是任务id
taskService.complete(task.getId());
}
/**
* 查询已经处理的任务
*/
@Test
public void findCompleteTaskList() {
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
.taskAssignee("zhangsan")
.finished().list();
for (HistoricTaskInstance historicTaskInstance : list) {
System.out.println("流程实例id:" + historicTaskInstance.getProcessInstanceId());
System.out.println("任务id:" + historicTaskInstance.getId());
System.out.println("任务负责人:" + historicTaskInstance.getAssignee());
System.out.println("任务名称:" + historicTaskInstance.getName());
}
}
/**
* 删除流程定义
*/
@Test
public void deleteDeployment() {
//部署id
String deploymentId = "qingjia:1:c493c327-bb02-11ed-8360-005056c00001";
// //删除流程定义,如果该流程定义已有流程实例启动则删除时出错
// repositoryService.deleteDeployment(deploymentId);
//设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式
repositoryService.deleteDeployment(deploymentId, true);
}
/**
* 启动流程实例,添加businessKey
*/
@Test
public void startUpProcessAddBusinessKey(){
// 启动流程实例,指定业务标识businessKey,也就是请假申请单id
ProcessInstance processInstance = runtimeService.
startProcessInstanceByKey("qingjia","1001");
// 输出
System.out.println("业务id:"+processInstance.getBusinessKey()); //1001
System.out.println("processInstance.getId() = " + processInstance.getId()); // 71f6803b-bb19-11ed-a845-005056c00001
}
/**
* 单个流程实例挂起
*/
@Test
public void SuspendProcessInstanceSingle() {
String processInstanceId = "71f6803b-bb19-11ed-a845-005056c00001";
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//获取到当前流程定义是否为暂停状态 suspended方法为true代表为暂停 false就是运行的
boolean suspended = processInstance.isSuspended();
if (suspended) {
runtimeService.activateProcessInstanceById(processInstanceId);
System.out.println("流程实例:" + processInstanceId + "激活");
} else {
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程实例:" + processInstanceId + "挂起");
}
}
/**
* 全部流程实例挂起
*/
@Test
public void suspendProcessInstanceAll() {
// 1、获取流程定义对象
ProcessDefinition qingjia = repositoryService.createProcessDefinitionQuery().processDefinitionKey("qingjia").singleResult();
// 2、调用流程定义对象的方法判断当前状态:挂起 激活
boolean suspended = qingjia.isSuspended();
if (suspended) {
// 暂定,那就可以激活
// 参数1:流程定义的id 参数2:是否激活 参数3:时间点
repositoryService.activateProcessDefinitionById(qingjia.getId(), true, null);
System.out.println("流程定义:" + qingjia.getId() + "激活");
} else {
repositoryService.suspendProcessDefinitionById(qingjia.getId(), true, null);
System.out.println("流程定义:" + qingjia.getId() + "挂起");
}
}
}
16.审批管理
1.审批类型设置
1.CRUD后台
@Api(value = "审批类型设置", tags = "审批类型管理设置")
@RestController
@RequestMapping("/admin/process/processType")
public class OaProcessTypeController {
@Autowired
private OaProcessTypeService processTypeService;
/**
* 新增审批类型
*
* @param processType
* @return
*/
@PreAuthorize("hasAuthority('bnt.processType.add')")
@ApiOperation(value = "新增")
@PostMapping("")
public Result save(@RequestBody ProcessType processType) {
processTypeService.save(processType);
return Result.ok();
}
/**
* 删除审批类型
*
* @param id
* @return
*/
@ApiOperation(value = "删除")
@DeleteMapping("/{id}")
public Result remove(@PathVariable Long id) {
processTypeService.removeById(id);
return Result.ok();
}
/**
* 修改审批类型
*
* @param processType
* @return
*/
@PreAuthorize("hasAuthority('bnt.processType.update')")
@ApiOperation(value = "修改")
@PutMapping("")
public Result updateById(@RequestBody ProcessType processType) {
processTypeService.updateById(processType);
return Result.ok();
}
/**
* 获取单个审批类型
*
* @param id
* @return
*/
@PreAuthorize("hasAuthority('bnt.processType.list')")
@ApiOperation(value = "获取")
@GetMapping("/{id}")
public Result get(@PathVariable Long id) {
ProcessType processType = processTypeService.getById(id);
return Result.ok(processType);
}
/**
* 获取全部审批类型
*
* @return
*/
@ApiOperation(value = "获取全部审批分类")
@GetMapping("findAll")
public Result findAll() {
return Result.ok(processTypeService.list());
}
/**
* 获取审批类型分页列表
*
* @param pageNum
* @param pageSize
* @return
*/
@ApiOperation(value = "获取分页列表")
@GetMapping("{pageNum}/{pageSize}")
public Result index(@PathVariable Long pageNum, @PathVariable Long pageSize) {
Page<ProcessType> pageInfo = new Page<>(pageNum, pageSize);
Page<ProcessType> pageModel = processTypeService.page(pageInfo);
return Result.ok(pageModel);
}
}
2.整合前端
定义api接口
src/api/process/processType.js
import request from '@/utils/request'
const api_name = '/admin/process/processType'
// 新增审批类型
export function saveProcessType(data) {
return request({
url: `${api_name}`,
method: 'post',
data: data
})
}
// 删除审批类型
export function removeProcessType(id) {
return request({
url: `${api_name}/${id}`,
method: 'delete'
})
}
// 修改审批类型
export function updateProcessType(data) {
return request({
url: `${api_name}`,
method: 'put',
data: data
})
}
// 查询审批类型详细
export function getProcessType(id) {
return request({
url: `${api_name}/${id}`,
method: 'get'
})
}
// 获取全部审批类型
export function findAll() {
return request({
url: `${api_name}/findAll`,
method: 'get'
})
}
// 查询审批类型列表
export function pageProcessType(pageNum, pageSize, query) {
return request({
url: `${api_name}/${pageNum}/${pageSize}`,
method: 'get',
params: query
})
}
页面展示
src/views/processSet/processType/index.vue
<template>
<div class="app-container">
<!-- CRUD -->
<el-row :gutter="10" class="mb8" style="margin-bottom: 10px">
<el-col :span="1.5">
<el-button
v-if="$hasBP('bnt.processType.add') "
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-if="$hasBP('bnt.processType.update') "
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-if="$hasBP('bnt.processType.remove') "
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出
</el-button>
</el-col>
</el-row>
<!-- 类型列表 -->
<el-table
v-loading="loading"
:data="processTypeList"
border
header-cell-style="background-color:#EEE;color:#444;height:41px;"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="50" align="center"/>
<el-table-column label="序号" width="70" align="center">
<template slot-scope="scope">
{{
(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1
}}
</template>
</el-table-column>
<el-table-column
key="name"
label="类型名称"
align="center"
prop="name"
:show-overflow-tooltip="true"
/>
<el-table-column
key="description"
label="描述"
align="center"
prop="description"
:show-overflow-tooltip="true"
/>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="160"
sortable
/>
<el-table-column
label="修改时间"
align="center"
prop="updateTime"
width="160"
sortable
/>
<el-table-column
label="操作"
align="center"
width="200"
class-name="small-padding fixed-width"
>
<template slot-scope="scope">
<el-button
v-if="$hasBP('bnt.processType.update') "
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改
</el-button>
<el-button
v-if="$hasBP('bnt.processType.remove') "
size="mini"
type="text"
icon="el-icon-delete"
:disabled="scope.row.ProcessTypename==='admin'"
@click="handleDelete(scope.row)"
>删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改审批类型对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="类型名称" prop="name">
<el-input
v-model="form.name"
placeholder="请输入类型名称"
maxlength="30"
:disabled="form.id != undefined"
/>
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input
v-model="form.description"
placeholder="请输入类型描述"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
pageProcessType,
getProcessType,
removeProcessType,
updateProcessType,
saveProcessType
} from '@/api/process/processType'
export default {
name: 'ProcessType',
data() {
return {
// 查询参数
queryParams: {
// 当前页码
pageNum: 1,
// 每页记录数
pageSize: 10
},
// 数据是否正在加载
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 总条数
total: 0,
// 类型表格数据
processTypeList: null,
// 弹出层标题
title: '',
open: false,
// 表单参数
form: {},
// 表单校验
rules: {
name: [
{ required: true, message: '类型名称不能为空', trigger: 'blur' },
{
min: 2,
max: 20,
message: '类型名称长度必须介于 2 和 20 之间',
trigger: 'blur'
}
]
}
}
},
created() {
this.getList()
},
methods: {
/** 查询类型列表 */
getList() {
this.loading = true
pageProcessType(
this.queryParams.pageNum,
this.queryParams.pageSize,
this.queryParams
).then((response) => {
this.processTypeList = response.data.records
this.total = response.data.total
this.loading = false
})
},
// 表单重置
reset() {
this.form = {
id: undefined,
name: undefined,
description: undefined
}
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = '添加类型'
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id || this.ids
getProcessType(id).then((response) => {
this.form = response.data
this.open = true
this.title = '修改类型'
})
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids
this.$confirm('您确定删除名称为[' + row.name + ']的类型吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
removeProcessType(ids)
.then((res) => {
this.$message.success('删除成功')
this.getList()
})
.catch((err) => {
this.$message.error('删除失败')
})
})
.catch(() => {
this.$message.info('已取消删除')
})
},
/** 导出按钮操作 */
handleExport() {
},
/** 导入按钮操作 */
handleImport() {
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.id)
this.single = selection.length != 1
this.multiple = !selection.length
},
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.form.id != undefined) {
updateProcessType(this.form).then((response) => {
this.$message.success('修改成功')
this.open = false
this.getList()
})
} else {
saveProcessType(this.form).then((response) => {
this.$message.success('新增成功')
this.open = false
this.getList()
})
}
}
})
},
/** 取消按钮*/
cancel() {
this.open = false
this.reset()
this.$refs['form'].resetFields()
}
}
}
</script>
<style scoped>
</style>
2.审批模板管理
1.CRUD后台
@Api(value = "审批模板管理", tags = "审批模板管理")
@RestController
@RequestMapping("/admin/process/processTemplate")
public class OaProcessTemplateController {
@Autowired
private OaProcessTemplateService processTemplateService;
/**
* 新增审批模板
*
* @param processTemplate
* @return
*/
//@PreAuthorize("hasAuthority('bnt.processTemplate.templateSet')")
@ApiOperation(value = "新增审批模板")
@PostMapping("")
public Result save(@RequestBody ProcessTemplate processTemplate) {
processTemplateService.save(processTemplate);
return Result.ok();
}
/**
* 删除审批模板
*
* @param id
* @return
*/
//@PreAuthorize("hasAuthority('bnt.processTemplate.remove')")
@ApiOperation(value = "删除审批模板")
@DeleteMapping("/{id}")
public Result remove(@PathVariable Long id) {
processTemplateService.removeById(id);
return Result.ok();
}
/**
* 修改审批模板
*
* @param processTemplate
* @return
*/
//@PreAuthorize("hasAuthority('bnt.processTemplate.templateSet')")
@ApiOperation(value = "修改审批模板")
@PutMapping("")
public Result updateById(@RequestBody ProcessTemplate processTemplate) {
processTemplateService.updateById(processTemplate);
return Result.ok();
}
/**
* 获取单个审批模板
*
* @param id
* @return
*/
//@PreAuthorize("hasAuthority('bnt.processTemplate.list')")
@ApiOperation(value = "获取单个审批模板")
@GetMapping("/{id}")
public Result get(@PathVariable Long id) {
ProcessTemplate processTemplate = processTemplateService.getById(id);
return Result.ok(processTemplate);
}
/**
* 分页查询审批模板
*
* @param pageNum
* @param pageSize
* @return
*/
@ApiOperation("获取分页查询审批模板数据")
@GetMapping("/{pageNum}/{pageSize}")
public Result index(@PathVariable Long pageNum, @PathVariable Long pageSize) {
Page<ProcessTemplate> pageInfo = new Page<>(pageNum, pageSize);
//分页查询审批模板,把审批类型对应名称查询
IPage<ProcessTemplate> pageModel =
processTemplateService.selectPageProcessTemplate(pageInfo);
return Result.ok(pageModel);
}
/**
* 上传流程定义(图片上传)
*
* @param file
* @return
* @throws FileNotFoundException
*/
@ApiOperation(value = "上传流程定义")
@PostMapping("/uploadProcessDefinition")
public Result uploadProcessDefinition(MultipartFile file) throws FileNotFoundException {
// 获取classes目录位置
String path = new File(ResourceUtils.getURL("classpath:").getPath()).getAbsolutePath();
// 设置上传文件夹
File tempFile = new File(path + "/processes/");
if (!tempFile.exists()) {
tempFile.mkdirs();
}
// 创建空文件,实现文件写入
String filename = file.getOriginalFilename();
File zipFile = new File(path + "/processes/" + filename);
// 保存文件
try {
file.transferTo(zipFile);
} catch (IOException e) {
return Result.fail();
}
Map<String, Object> map = new HashMap<>();
//根据上传地址后续部署流程定义,文件名称为流程定义的默认key
map.put("processDefinitionPath", "processes/" + filename);
map.put("processDefinitionKey", filename.substring(0, filename.lastIndexOf(".")));
return Result.ok(map);
}
/**
* 部署流程定义(发布)
* @param id
* @return
*/
@ApiOperation(value = "发布审批模板")
@GetMapping("/publish/{id}")
public Result publish(@PathVariable Long id) {
// 修改模板的发布状态 status==1 代表已发布
// 流程定义部署
processTemplateService.publish(id);
return Result.ok();
}
}
com.atguigu.process.service.impl.OaProcessTemplateServiceImpl
@Service
public class OaProcessTemplateServiceImpl extends ServiceImpl<OaProcessTemplateMapper, ProcessTemplate> implements OaProcessTemplateService {
@Autowired
private OaProcessTypeService processTypeService;
@Autowired
private OaProcessService processService;
/**
* 分页查询审批模板,把审批类型对应名称查询
*
* @param pageInfo
* @return
*/
@Override
public IPage<ProcessTemplate> selectPageProcessTemplate(Page<ProcessTemplate> pageInfo) {
// 1、调用mapper的方法实现分页查询
Page<ProcessTemplate> processTemplatePage = baseMapper.selectPage(pageInfo, null);
// 2、 第一步分页查询返回分页数据,从分页数据获取列表list集合
List<ProcessTemplate> processTemplateList = processTemplatePage.getRecords();
// 3、 遍历list集合,得到每个对象的审批类型id
for (ProcessTemplate processTemplate : processTemplateList) {
// 得到每个对象的审批类型id
Long processTypeId = processTemplate.getProcessTypeId();
// 4、 根据审批类型id,查询获取对应名称
LambdaQueryWrapper<ProcessType> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ProcessType::getId, processTypeId);
ProcessType processType = processTypeService.getOne(queryWrapper);
if (processType == null) {
continue;
}
// 5、 完成最终封装processTypeName
processTemplate.setProcessTypeName(processType.getName());
}
return processTemplatePage;
}
/**
* 流程定义部署:修改模板的发布状态 status==1 代表已发布
*
* @param id
*/
@Override
public void publish(Long id) {
// 修改模板的发布状态 status==1 代表已发布
ProcessTemplate processTemplate = baseMapper.selectById(id);
processTemplate.setStatus(1);
baseMapper.updateById(processTemplate);
// 流程定义部署
if (StringUtils.isEmpty(processTemplate.getProcessDefinitionPath())) {
processService.deployByZip(processTemplate.getProcessDefinitionPath());
}
}
}
2.整合前端
定义api接口
src/api/process/processTemplate.js
import request from '@/utils/request'
const api_name = '/admin/process/processTemplate'
// 新增审批模板
export function saveProcessTemplate(data) {
return request({
url: `${api_name}`,
method: 'post',
data: data
})
}
// 删除审批模板
export function removeProcessTemplate(id) {
return request({
url: `${api_name}/${id}`,
method: 'delete'
})
}
// 修改审批模板
export function updateProcessTemplate(data) {
return request({
url: `${api_name}`,
method: 'put',
data: data
})
}
// 查询审批模板详细
export function getProcessTemplate(id) {
return request({
url: `${api_name}/${id}`,
method: 'get'
})
}
// 查询审批模板列表
export function pageProcessTemplate(pageNum, pageSize, query) {
return request({
url: `${api_name}/${pageNum}/${pageSize}`,
method: 'get',
params: query
})
}
// 发布审批模板
export function publish(id) {
return request({
url: `${api_name}/publish/${id}`,
method: 'get'
})
}
页面展示
src/views/processSet/processTemplate/index.vue
<template>
<div class="app-container">
<!-- CRUD -->
<el-row :gutter="10" class="mb8" style="margin-bottom: 10px">
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>添加审批模板
</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-if="$hasBP('bnt.processTemplate.remove') "
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出
</el-button>
</el-col>-->
</el-row>
<!-- 审批列表 -->
<el-table
v-loading="loading"
:data="processTemplateList"
border
header-cell-style="background-color:#EEE;color:#444;height:41px;"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="序号" width="70" align="center">
<template slot-scope="scope">
{{
(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1
}}
</template>
</el-table-column>
<el-table-column
key="name"
label="审批名称"
align="center"
prop="name"
:show-overflow-tooltip="true"
/>
<el-table-column label="图标">
<template slot-scope="scope">
<img :src="scope.row.iconUrl" style="width: 30px;height: 30px;vertical-align: text-bottom;">
</template>
</el-table-column>
<el-table-column
key="processTypeName"
label="审批类型"
align="center"
prop="processTypeName"
:show-overflow-tooltip="true"
/>
<el-table-column
key="description"
label="描述"
align="center"
prop="description"
:show-overflow-tooltip="true"
/>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="160"
sortable
/>
<el-table-column
label="修改时间"
align="center"
prop="updateTime"
width="160"
sortable
/>
<el-table-column
label="操作"
align="center"
width="300"
class-name="small-padding fixed-width"
>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleShow(scope.row)"
>查看审批设置
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改审批设置
</el-button>
<el-button
v-if="$hasBP('bnt.processTemplate.remove') "
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除
</el-button>
<el-button v-if="scope.row.status == 0" type="text" size="mini" :disabled="$hasBP('bnt.processTemplate.publish') === false" @click="publish(scope.row)">发布</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 查看审批模板对话框 -->
<el-dialog :title="title" :visible.sync="open" width="35%" append-to-body>
<h3>基本信息</h3>
<el-divider />
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="审批类型" prop="processTypeName">{{ form.processTypeName }}</el-form-item>
<el-form-item label="审批名称" prop="name">{{ form.name }}</el-form-item>
<el-form-item label="创建时间" prop="createTime">{{ form.createTime }}</el-form-item>
</el-form>
<h3>表单信息</h3>
<el-divider />
<div>
<form-create
:rule="rule"
:option="option"
/>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="open = false">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
pageProcessTemplate, publish,
removeProcessTemplate,
saveProcessTemplate,
updateProcessTemplate
} from '@/api/process/processTemplate'
export default {
name: 'ProcessTemplate',
data() {
return {
// 查询参数
queryParams: {
// 当前页码
pageNum: 1,
// 每页记录数
pageSize: 10
},
// 数据是否正在加载
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 总条数
total: 0,
// 审批表格数据
processTemplateList: null,
// 弹出层标题
title: '',
open: false,
form: {},
rule: [],
option: {}
}
},
created() {
this.getList()
},
methods: {
/** 查询审批列表 */
getList() {
this.loading = true
pageProcessTemplate(
this.queryParams.pageNum,
this.queryParams.pageSize,
this.queryParams
).then((response) => {
this.processTemplateList = response.data.records
this.total = response.data.total
this.loading = false
})
},
// 表单重置
reset() {
this.form = {
id: undefined,
name: undefined,
description: undefined
}
},
/** 新增按钮操作 */
handleAdd() {
this.$router.push('/processSet/templateSet')
},
/** 查看审批设置 */
handleShow(row) {
this.title = '查看审批设置'
this.rule = JSON.parse(row.formProps)
this.option = JSON.parse(row.formOptions)
this.form = row
this.open = true
},
/** 修改按钮操作 */
handleUpdate(row) {
const id = row.id || this.ids
this.$router.push('/processSet/templateSet?id=' + id)
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids
this.$confirm('您确定删除名称为[' + row.name + ']的审批模板吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
removeProcessTemplate(ids)
.then((res) => {
this.$message.success('删除成功')
this.getList()
})
.catch((err) => {
this.$message.error('删除失败')
})
})
.catch(() => {
this.$message.info('已取消删除')
})
},
/** 发布审批模板*/
publish(row) {
const id = row.id || this.ids
this.$confirm('是否确认发布[' + row.name + ']的审批模板吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
publish(id).then(response => {
this.$message.success('发布成功')
this.getList()
// eslint-disable-next-line handle-callback-err
}).catch(error => {
this.$message.error('发布失败')
})
})
.catch(() => {
})
},
/** 导出按钮操作 */
handleExport() {
},
/** 导入按钮操作 */
handleImport() {
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.id)
this.single = selection.length != 1
this.multiple = !selection.length
},
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.form.id != undefined) {
updateProcessTemplate(this.form).then((response) => {
this.$message.success('修改成功')
this.open = false
this.getList()
})
} else {
saveProcessTemplate(this.form).then((response) => {
this.$message.success('新增成功')
this.open = false
this.getList()
})
}
}
})
},
/** 取消按钮*/
cancel() {
this.open = false
this.reset()
this.$refs['form'].resetFields()
}
}
}
</script>
<style scoped>
</style>
添加审批模板
1、添加依赖
在package.json文件dependencies添加依赖,
"@form-create/designer": "^1.0.10",
"@form-create/element-ui": "^2.5.33",
2、在 main.js 中写入以下内容:
import formCreate from '@form-create/element-ui'
import FcDesigner from '@form-create/designer'
Vue.use(formCreate)
Vue.use(FcDesigner)
3、模板设置页面
src/views/processSet/processTemplate/templateSet.vue
<template>
<div class="app-container">
<el-steps :active="stepIndex" finish-status="success">
<el-step title="基本设置" />
<el-step title="表单设置" />
<el-step title="流程设置" />
</el-steps>
<div class="tools-div">
<el-button v-if="stepIndex > 1" icon="el-icon-check" type="primary" size="small" round @click="pre()">上一步
</el-button>
<el-button icon="el-icon-check" type="primary" size="small" round @click="next()">{{
stepIndex == 3 ? '提交保存' : '下一步'
}}
</el-button>
<el-button type="primary" size="small" @click="back()">返回</el-button>
</div>
<!-- 第一步 -->
<div v-show="stepIndex == 1" style="margin-top: 20px;">
<el-form ref="flashPromotionForm" label-width="150px" size="small" style="padding-right: 40px;">
<el-form-item label="审批类型">
<el-select v-model="processTemplate.processTypeId" placeholder="请选择审批类型">
<el-option v-for="item in processTypeList" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="审批名称">
<el-input v-model="processTemplate.name" />
</el-form-item>
<el-form-item label="审批图标">
<el-select v-model="processTemplate.iconUrl" placeholder="请选择审批图标">
<el-option v-for="item in iconUrlList" :label="item.iconUrl" :value="item.iconUrl">
<img :src="item.iconUrl" style="width: 30px;height: 30px;vertical-align: text-bottom;">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="描述">
<el-input v-model="processTemplate.description" />
</el-form-item>
</el-form>
</div>
<!-- 第二步 -->
<div v-show="stepIndex == 2" style="margin-top: 20px;">
<!--表单构建器-->
<fc-designer ref="designer" class="form-build" />
</div>
<!-- 第三步 -->
<div v-show="stepIndex == 3" style="margin-top: 20px;">
<el-upload
class="upload-demo"
drag
action="/dev-api/admin/process/processTemplate/uploadProcessDefinition"
:headers="uploadHeaders"
multiple="false"
:before-upload="beforeUpload"
:on-success="onUploadSuccess"
:file-list="fileList"
>
<i class="el-icon-upload" />
<div class="el-upload__text">将Activiti流程设计文件拖到此处,或<em>点击上传</em></div>
<div slot="tip" class="el-upload__tip">只能上传zip压缩文件,且不超过2048kb</div>
</el-upload>
</div>
</div>
</template>
<script>
import store from '@/store'
import { findAll } from '@/api/process/processType'
import { getProcessTemplate, saveProcessTemplate, updateProcessTemplate } from '@/api/process/processTemplate'
const defaultForm = {
id: '',
name: '',
iconUrl: '',
formProps: '',
formOptions: '',
processDefinitionKey: '',
processDefinitionPath: '',
description: ''
}
export default {
data() {
return {
stepIndex: 1,
processTypeList: [],
processTemplate: defaultForm,
iconUrlList: [
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1t695CFYqK1RjSZLeXXbXppXa-102-102.png', tag: '请假' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1bHOWCSzqK1RjSZFjXXblCFXa-112-112.png', tag: '出差' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1cbCYCPTpK1RjSZKPXXa3UpXa-112-112.png', tag: '机票出差' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1cbCYCPTpK1RjSZKPXXa3UpXa-112-112.png', tag: '机票改签' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1e76lCOLaK1RjSZFxXXamPFXa-112-112.png', tag: '外出' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1Yfa0CG6qK1RjSZFmXXX0PFXa-112-112.png', tag: '补卡申请' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1Y8PlCNjaK1RjSZKzXXXVwXXa-112-112.png', tag: '加班' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB11X99CNTpK1RjSZFKXXa2wXXa-102-102.png', tag: '居家隔离' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1_YG.COrpK1RjSZFhXXXSdXXa-102-102.png', tag: '请假' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB13ca1CMDqK1RjSZSyXXaxEVXa-102-102.png', tag: '调岗' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1U9iBCSzqK1RjSZPcXXbTepXa-102-102.png', tag: '离职' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB11pS_CFzqK1RjSZSgXXcpAVXa-102-102.png', tag: '费用申请' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1t695CFYqK1RjSZLeXXbXppXa-102-102.png', tag: '用章申请' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB13f_aCQzoK1RjSZFlXXai4VXa-102-102.png', tag: '携章外出' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1_YG.COrpK1RjSZFhXXXSdXXa-102-102.png', tag: '学期内分期' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1_YG.COrpK1RjSZFhXXXSdXXa-102-102.png', tag: '特殊学费' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1Yfa0CG6qK1RjSZFmXXX0PFXa-112-112.png', tag: '充值卡申领' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1e76lCOLaK1RjSZFxXXamPFXa-112-112.png', tag: '礼品申领' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1FNG.CMHqK1RjSZFgXXa7JXXa-102-102.png', tag: '邮寄快递申请' },
{ iconUrl: 'https://gw.alicdn.com/imgextra/i3/O1CN01LLn0YV1LhBXs7T2iO_!!6000000001330-2-tps-120-120.png', tag: '合同审批' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1e76lCOLaK1RjSZFxXXamPFXa-112-112.png', tag: '合同借阅' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1e76lCOLaK1RjSZFxXXamPFXa-112-112.png', tag: '魔点临时开门权限' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1bHOWCSzqK1RjSZFjXXblCFXa-112-112.png', tag: '北京科技园车证审批' },
{ iconUrl: 'https://gw.alicdn.com/tfs/TB1e76lCOLaK1RjSZFxXXamPFXa-112-112.png', tag: '魔点访客提前预约审批' }
],
uploadHeaders: {
'token': store.getters.token
},
fileList: []
}
},
created() {
const id = this.$route.query.id
console.log(id)
if (id > 0) {
this.fetchDataById(id)
}
this.fetchProcessTypeData()
},
methods: {
pre() {
this.stepIndex -= 1
},
next() {
if (this.stepIndex === 2) {
this.processTemplate.formProps = JSON.stringify(this.$refs.designer.getRule())
this.processTemplate.formOptions = JSON.stringify(this.$refs.designer.getOption())
console.log(JSON.stringify(this.processTemplate))
}
if (this.stepIndex === 3) {
this.saveOrUpdate()
}
this.stepIndex += 1
},
fetchProcessTypeData() {
findAll().then(response => {
this.processTypeList = response.data
})
},
fetchDataById(id) {
getProcessTemplate(id).then(response => {
this.processTemplate = response.data
// 给表单设计器赋值
this.$refs.designer.setRule(JSON.parse(this.processTemplate.formProps))
this.$refs.designer.setOption(JSON.parse(this.processTemplate.formOptions))
this.fileList = [{
name: this.processTemplate.processDefinitionPath,
url: this.processTemplate.processDefinitionPath
}]
})
},
saveOrUpdate() {
this.saveBtnDisabled = true // 防止表单重复提交
if (!this.processTemplate.id) {
this.saveData()
} else {
this.updateData()
}
},
// 新增
saveData() {
saveProcessTemplate(this.processTemplate).then(response => {
this.$router.push('/processSet/processTemplate')
})
},
// 根据id更新记录
updateData() {
updateProcessTemplate(this.processTemplate).then(response => {
this.$router.push('/processSet/processTemplate')
})
},
// 文件上传限制条件
beforeUpload(file) {
const isZip = file.type === 'application/x-zip-compressed'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isZip) {
this.$message.error('文件格式不正确!')
return false
}
if (!isLt2M) {
this.$message.error('上传大小不能超过 2MB!')
return false
}
return true
},
// 上传成功的回调
onUploadSuccess(res, file) {
// 填充上传文件列表
this.processTemplate.processDefinitionPath = res.data.processDefinitionPath
this.processTemplate.processDefinitionKey = res.data.processDefinitionKey
},
back() {
this.$router.push('/processSet/processTemplate')
}
}
}
</script>
3.审批列表
1.CRUD后台
com.atguigu.process.controller.OaProcessController
@Api(value = "审批列表管理", tags = "审批列表管理")
@RestController
@RequestMapping(value = "/admin/process")
public class OaProcessController {
@Autowired
private OaProcessService processService;
/**
* 审批列表管理
*
* @param pageNum
* @param pageSize
* @param processQueryVo
* @return
*/
@ApiOperation(value = "获取分页列表")
@GetMapping("/{pageNum}/{pageSize}")
public Result index(@PathVariable Long pageNum,
@PathVariable Long pageSize,
ProcessQueryVo processQueryVo) {
Page<ProcessVo> pageInfo = new Page<>(pageNum, pageSize);
IPage<ProcessVo> pageModel = processService.selectPage(pageInfo, processQueryVo);
return Result.ok(pageModel);
}
}
com.atguigu.process.service.impl.OaProcessServiceImpl
@Service
public class OaProcessServiceImpl extends ServiceImpl<OaProcessMapper, Process> implements OaProcessService {
@Autowired
private RepositoryService repositoryService;
@Autowired
private SysUserService sysUserService;
@Autowired
private OaProcessTemplateService processTemplateService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private OaProcessRecordService processRecordService;
@Autowired
private HistoryService historyService;
/**
* 审批管理列表
*
* @param pageInfo
* @param processQueryVo
* @return
*/
@Override
public IPage<ProcessVo> selectPage(Page<ProcessVo> pageInfo, ProcessQueryVo processQueryVo) {
IPage<ProcessVo> pageModel = baseMapper.selectPage(pageInfo, processQueryVo);
return pageModel;
}
/**
* 流程定义部署
*
* @param deployPath
*/
@Override
public void deployByZip(String deployPath) {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(deployPath);
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 部署
Deployment deployment = repositoryService.createDeployment().addZipInputStream(zipInputStream).deploy();
System.out.println("deployment.getId() = " + deployment.getId());
System.out.println("deployment.getName() = " + deployment.getName());
}
}
com.atguigu.process.mapper.OaProcessMapper
public interface OaProcessMapper extends BaseMapper<Process> {
//审批管理列表
IPage<ProcessVo> selectPage(Page<ProcessVo> pageInfo, @Param("vo") ProcessQueryVo processQueryVo);
}
src/main/resources/mapper/OaProcessMapper.xml
<?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.atguigu.process.mapper.OaProcessMapper">
<select id="selectPage" resultType="com.atguigu.vo.process.ProcessVo">
SELECT
a.id,a.process_code,a.user_id,a.process_template_id,a.process_type_id,a.title,a.description,a.form_values,a.process_instance_id,a.current_auditor,a.status,a.create_time,a.update_time,
b.name AS processTemplateName,
c.name AS processTypeName,
d.name
FROM oa_process a
LEFT JOIN sys_user d ON a.user_id =d.id
LEFT JOIN oa_process_template b ON a.process_template_id = b.id
LEFT JOIN oa_process_type c ON a.process_type_id = c.id
<where>
<if test="vo.keyword != null and vo.keyword != ''">
and (a.process_code like CONCAT('%',#{vo.keyword},'%') or
a.title like CONCAT('%',#{vo.keyword},'%'))
</if>
<if test="vo.userId != null and vo.userId != ''">
and a.user_id = #{vo.userId}
</if>
<if test="vo.status != null and vo.status != ''">
and a.status = #{vo.status}
</if>
<if test="vo.createTimeBegin != null and vo.createTimeBegin != ''">
and a.create_time >= #{vo.createTimeBegin}
</if>
<if test="vo.createTimeEnd != null and vo.createTimeEnd != ''">
and a.create_time <= #{vo.createTimeEnd}
</if>
</where>
</select>
</mapper>
2.整合前端
定义api接口请求函数
src/api/process/process.js
import request from '@/utils/request'
const api_name = '/admin/process'
// 查询审批类型列表
export function pageProcess(pageNum, pageSize, query) {
return request({
url: `${api_name}/${pageNum}/${pageSize}`,
method: 'get',
params: query
})
}
页面在展示
src/views/processMgr/process/index.vue
<template>
<div class="app-container">
<!-- 查询条件 -->
<el-form ref="queryForm" :model="queryParams" size="small" :inline="true">
<el-form-item label="关键字" prop="keyword">
<el-input
v-model="queryParams.keyword"
placeholder="审批编号/标题/手机号码/姓名"
clearable
style="width: 250px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态">
<el-select
v-model="queryParams.status"
placeholder="请选择状态"
>
<el-option
v-for="item in statusList"
:key="item.status"
:label="item.name"
:value="item.status"
/>
</el-select>
</el-form-item>
<el-form-item label="操作时间">
<el-date-picker
v-model="createTimes"
type="datetimerange"
:picker-options="pickerOptions"
value-format="yyyy-MM-dd HH:mm:ss"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
style="width: 360px"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索
</el-button>
<el-button
icon="el-icon-refresh"
size="mini"
@click="resetQuery"
>重置
</el-button>
</el-form-item>
</el-form>
<!-- 审批列表 -->
<el-table
v-loading="loading"
:data="processList"
border
header-cell-style="background-color:#EEE;color:#444;height:41px;"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="序号" width="70" align="center">
<template slot-scope="scope">
{{
(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1
}}
</template>
</el-table-column>
<el-table-column
key="processCode"
label="审批编号"
align="center"
prop="processCode"
:show-overflow-tooltip="true"
/>
<el-table-column
key="title"
label="标题"
align="center"
prop="title"
:show-overflow-tooltip="true"
/>
<el-table-column
key="name"
label="审批"
align="center"
prop="name"
:show-overflow-tooltip="true"
/>
<el-table-column
key="processTypeName"
label="审批类型"
align="center"
prop="processTypeName"
:show-overflow-tooltip="true"
/>
<el-table-column
key="processTemplateName"
label="审批模板"
align="center"
prop="processTemplateName"
:show-overflow-tooltip="true"
/>
<el-table-column
key="description"
label="描述"
align="center"
prop="description"
:show-overflow-tooltip="true"
/>
<el-table-column key="status" label="状态" align="center">
<template slot-scope="scope">
<span> {{ scope.row.status === 1 ? '审批中' : scope.row.status === 2 ? '完成' : '驳回' }}</span>
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="160"
sortable
/>
<el-table-column
label="操作"
align="center"
width="120"
class-name="small-padding fixed-width"
>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleShow(scope.row)"
>查看
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script>
import { pageProcess } from '@/api/process/process'
export default {
name: 'Process',
data() {
return {
// 查询参数
queryParams: {
// 当前页码
pageNum: 1,
// 每页记录数
pageSize: 10,
// 关键字
keyword: undefined,
status: undefined,
createTimeBegin: undefined,
createTimeEnd: undefined
},
// 状态选项
statusList: [
{ 'status': '1', 'name': '进行中' },
{ 'status': '2', 'name': '已完成' },
{ 'status': '-1', 'name': '驳回' }
],
// 创建时间
createTimes: [],
// 时间日期选择器快捷选项
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit('pick', [start, end])
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit('pick', [start, end])
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
picker.$emit('pick', [start, end])
}
}, {
text: '最近半年',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 183)
picker.$emit('pick', [start, end])
}
}, {
text: '最近一年',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 365)
picker.$emit('pick', [start, end])
}
}
]
},
// 数据是否正在加载
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 总条数
total: 0,
// 审批表格数据
processList: null,
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
// 表单参数
form: {}
}
},
created() {
this.getList()
},
methods: {
/** 查询审批列表 */
getList() {
this.loading = true
if (this.createTimes && this.createTimes.length === 2) {
this.queryParams.createTimeBegin = this.createTimes[0]
this.queryParams.createTimeEnd = this.createTimes[1]
} else {
this.queryParams.createTimeBegin = undefined
this.queryParams.createTimeEnd = undefined
}
pageProcess(
this.queryParams.pageNum,
this.queryParams.pageSize,
this.queryParams
).then((response) => {
this.processList = response.data.records
console.log('审批列表:', this.processList)
this.total = response.data.total
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.createTimes = []
this.$refs['queryForm'].resetFields()
this.handleQuery()
},
// 表单重置
reset() {
this.form = {
id: undefined,
username: undefined,
name: undefined,
password: undefined,
phone: undefined,
description: undefined
}
},
/** 查看按钮操作 */
handleShow(row) {
this.reset()
const id = row.id || this.ids
// getUser(id).then((response) => {
// this.form = response.data
// this.open = true
// this.title = '查看审批详情'
// })
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
}
}
}
</script>
<style scoped>
</style>