Commit 8a10568b24c3677cd3d58430dfe866d9faaec055

Authored by YunaiV
1 parent 749cb5d7

1. 修改 Parser.vue 组件,实现 submit 传递 conf 和 values 参数

2. 完成流程创建的前端 UI 界面
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmDefinitionConvert.java
@@ -17,6 +17,7 @@ import org.mapstruct.factory.Mappers; @@ -17,6 +17,7 @@ import org.mapstruct.factory.Mappers;
17 17
18 import java.util.List; 18 import java.util.List;
19 import java.util.Map; 19 import java.util.Map;
  20 +import java.util.function.Function;
20 21
21 /** 22 /**
22 * Bpm 流程定义的 Convert 23 * Bpm 流程定义的 Convert
@@ -59,10 +60,18 @@ public interface BpmDefinitionConvert { @@ -59,10 +60,18 @@ public interface BpmDefinitionConvert {
59 60
60 BpmProcessDefinitionExtDO convert2(BpmDefinitionCreateReqDTO bean); 61 BpmProcessDefinitionExtDO convert2(BpmDefinitionCreateReqDTO bean);
61 62
62 - @Named("convertList3")  
63 - List<BpmProcessDefinitionRespVO> convertList3(List<ProcessDefinition> list); 63 + default List<BpmProcessDefinitionRespVO> convertList3(List<ProcessDefinition> list,
  64 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap) {
  65 + return CollectionUtils.convertList(list, processDefinition -> {
  66 + BpmProcessDefinitionRespVO respVO = convert3(processDefinition);
  67 + BpmProcessDefinitionExtDO processDefinitionExtDO = processDefinitionDOMap.get(processDefinition.getId());
  68 + if (processDefinitionExtDO != null) {
  69 + respVO.setFormId(processDefinitionExtDO.getFormId());
  70 + }
  71 + return respVO;
  72 + });
  73 + }
64 74
65 - @Named("convert3")  
66 @Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState") 75 @Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState")
67 BpmProcessDefinitionRespVO convert3(ProcessDefinition bean); 76 BpmProcessDefinitionRespVO convert3(ProcessDefinition bean);
68 77
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java
@@ -79,8 +79,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -79,8 +79,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
79 Map<String, Deployment> deploymentMap = getDeploymentMap(deploymentIds); 79 Map<String, Deployment> deploymentMap = getDeploymentMap(deploymentIds);
80 80
81 // 获得 BpmProcessDefinitionDO Map 81 // 获得 BpmProcessDefinitionDO Map
82 - List<BpmProcessDefinitionExtDO> processDefinitionDOs = Collections.emptyList();  
83 - processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds( 82 + List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
84 convertList(processDefinitions, ProcessDefinition::getId)); 83 convertList(processDefinitions, ProcessDefinition::getId));
85 Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = CollectionUtils.convertMap(processDefinitionDOs, 84 Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = CollectionUtils.convertMap(processDefinitionDOs,
86 BpmProcessDefinitionExtDO::getProcessDefinitionId); 85 BpmProcessDefinitionExtDO::getProcessDefinitionId);
@@ -104,8 +103,16 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -104,8 +103,16 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
104 } else if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), listReqVO.getSuspensionState())) { 103 } else if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), listReqVO.getSuspensionState())) {
105 definitionQuery.active(); 104 definitionQuery.active();
106 } 105 }
  106 + // 执行查询
  107 + List<ProcessDefinition> processDefinitions = definitionQuery.list();
  108 +
  109 + // 获得 BpmProcessDefinitionDO Map
  110 + List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
  111 + convertList(processDefinitions, ProcessDefinition::getId));
  112 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = CollectionUtils.convertMap(processDefinitionDOs,
  113 + BpmProcessDefinitionExtDO::getProcessDefinitionId);
107 // 执行查询,并返回 114 // 执行查询,并返回
108 - return BpmDefinitionConvert.INSTANCE.convertList3(definitionQuery.list()); 115 + return BpmDefinitionConvert.INSTANCE.convertList3(processDefinitions, processDefinitionDOMap);
109 } 116 }
110 117
111 @Override 118 @Override
yudao-admin-ui/src/api/bpm/definition.js
@@ -8,6 +8,14 @@ export function getProcessDefinitionPage(query) { @@ -8,6 +8,14 @@ export function getProcessDefinitionPage(query) {
8 }) 8 })
9 } 9 }
10 10
  11 +export function getProcessDefinitionList(query) {
  12 + return request({
  13 + url: '/bpm/process-definition/list',
  14 + method: 'get',
  15 + params: query
  16 + })
  17 +}
  18 +
11 export function getProcessDefinitionBpmnXML(id) { 19 export function getProcessDefinitionBpmnXML(id) {
12 return request({ 20 return request({
13 url: '/bpm/process-definition/get-bpmn-xml?id=' + id, 21 url: '/bpm/process-definition/get-bpmn-xml?id=' + id,
yudao-admin-ui/src/api/bpm/processInstance.js
@@ -8,6 +8,14 @@ export function getMyProcessInstancePage(query) { @@ -8,6 +8,14 @@ export function getMyProcessInstancePage(query) {
8 }) 8 })
9 } 9 }
10 10
  11 +export function createProcessInstance(data) {
  12 + return request({
  13 + url: '/bpm/process-instance/create',
  14 + method: 'POST',
  15 + data: data
  16 + })
  17 +}
  18 +
11 export function cancelProcessInstance(id, reason) { 19 export function cancelProcessInstance(id, reason) {
12 return request({ 20 return request({
13 url: '/bpm/process-instance/cancel', 21 url: '/bpm/process-instance/cancel',
yudao-admin-ui/src/components/parser/Parser.vue
@@ -173,8 +173,13 @@ export default { @@ -173,8 +173,13 @@ export default {
173 submitForm() { 173 submitForm() {
174 this.$refs[this.formConf.formRef].validate(valid => { 174 this.$refs[this.formConf.formRef].validate(valid => {
175 if (!valid) return false 175 if (!valid) return false
176 - // 触发sumit事件  
177 - this.$emit('submit', this[this.formConf.formModel]) 176 + // 触发 submit 事件
  177 + // update by 芋道源码
  178 + // this.$emit('submit', this[this.formConf.formModel])
  179 + this.$emit('submit', {
  180 + conf: this.formConfCopy,
  181 + values: this[this.formConf.formModel]
  182 + })
178 return true 183 return true
179 }) 184 })
180 } 185 }
yudao-admin-ui/src/views/bpm/processInstance/create.vue
1 <template> 1 <template>
2 <div class="app-container"> 2 <div class="app-container">
3 - <!-- 列表 -->  
4 - <el-table v-loading="loading" :data="list">  
5 - <el-table-column label="定义编号" align="center" prop="id" width="400" />  
6 - <el-table-column label="定义名称" align="center" prop="name" width="100">  
7 - <template slot-scope="scope">  
8 - <el-button type="text" @click="handleBpmnDetail(scope.row)">  
9 - <span>{{ scope.row.name }}</span>  
10 - </el-button>  
11 - </template>  
12 - </el-table-column>  
13 - <el-table-column label="定义分类" align="center" prop="category" width="100">  
14 - <template slot-scope="scope">  
15 - <span>{{ getDictDataLabel(DICT_TYPE.BPM_MODEL_CATEGORY, scope.row.category) }}</span>  
16 - </template>  
17 - </el-table-column>  
18 - <el-table-column label="表单信息" align="center" prop="formId">  
19 - <template slot-scope="scope">  
20 - <el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">  
21 - <span>{{ scope.row.formName }}</span>  
22 - </el-button>  
23 - <label v-else>暂无表单</label>  
24 - </template>  
25 - </el-table-column>  
26 - <el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">  
27 - <template slot-scope="scope">  
28 - <el-tag size="medium" v-if="scope.row">v{{ scope.row.version }}</el-tag>  
29 - <el-tag size="medium" type="warning" v-else>未部署</el-tag>  
30 - </template>  
31 - </el-table-column>  
32 - <el-table-column label="状态" align="center" prop="version" width="80">  
33 - <template slot-scope="scope">  
34 - <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>  
35 - <el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>  
36 - </template>  
37 - </el-table-column>  
38 - <el-table-column label="部署时间" align="center" prop="deploymentTime" width="180">  
39 - <template slot-scope="scope">  
40 - <span>{{ parseTime(scope.row.deploymentTime) }}</span>  
41 - </template>  
42 - </el-table-column>  
43 - <el-table-column label="定义描述" align="center" prop="description" width="300" show-overflow-tooltip />  
44 - </el-table> 3 + <!-- 第一步,通过流程定义的列表,选择对应的流程 -->
  4 + <div v-if="!selectProcessInstance">
  5 + <el-table v-loading="loading" :data="list">
  6 + <el-table-column label="流程名称" align="center" prop="name" width="200">
  7 + <template slot-scope="scope">
  8 + <el-button type="text" @click="handleBpmnDetail(scope.row)">
  9 + <span>{{ scope.row.name }}</span>
  10 + </el-button>
  11 + </template>
  12 + </el-table-column>
  13 + <el-table-column label="流程分类" align="center" prop="category" width="100">
  14 + <template slot-scope="scope">
  15 + <span>{{ getDictDataLabel(DICT_TYPE.BPM_MODEL_CATEGORY, scope.row.category) }}</span>
  16 + </template>
  17 + </el-table-column>
  18 + <el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
  19 + <template slot-scope="scope">
  20 + <el-tag size="medium" v-if="scope.row">v{{ scope.row.version }}</el-tag>
  21 + </template>
  22 + </el-table-column>
  23 + <el-table-column label="流程描述" align="center" prop="description" width="300" show-overflow-tooltip />
  24 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  25 + <template slot-scope="scope">
  26 + <el-button type="text" size="small" icon="el-icon-plus" @click="handleSelect(scope.row)">选择</el-button>
  27 + </template>
  28 + </el-table-column>
  29 + </el-table>
  30 + </div>
  31 + <!-- 第二步,填写表单,进行流程的提交 -->
  32 + <div v-else>
  33 + <el-card class="box-card" >
  34 + <div slot="header" class="clearfix">
  35 + <span class="el-icon-document">{{ selectProcessInstance.name }}</span>
  36 + <el-button style="float: right;" type="primary" @click="selectProcessInstance = undefined">选择其它流程</el-button>
  37 + </div>
  38 + <el-col :span="16" :offset="6">
  39 + <div>
  40 + <parser :key="new Date().getTime()" :form-conf="detailForm" @submit="submitForm" />
  41 + </div>
  42 + </el-col>
  43 + </el-card>
  44 + </div>
45 45
46 - <!-- 流程表单配置详情 -->  
47 - <el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>  
48 - <parser :key="new Date().getTime()" :form-conf="detailForm" />  
49 - </el-dialog>  
50 -  
51 - <!-- 流程模型图的预览 -->  
52 - <el-dialog title="流程图" :visible.sync="showBpmnOpen" width="80%" append-to-body> 46 + <el-card class="box-card">
  47 + <div slot="header" class="clearfix">
  48 + <span class="el-icon-picture-outline">流程图</span>
  49 + </div>
53 <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" /> 50 <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
54 - </el-dialog> 51 + </el-card>
55 52
56 - <!-- 分页组件 -->  
57 - <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"  
58 - @pagination="getList"/>  
59 </div> 53 </div>
60 </template> 54 </template>
61 55
62 <script> 56 <script>
63 -import {getProcessDefinitionBpmnXML, getProcessDefinitionPage} from "@/api/bpm/definition"; 57 +import {getProcessDefinitionBpmnXML, getProcessDefinitionList} from "@/api/bpm/definition";
64 import {DICT_TYPE, getDictDatas} from "@/utils/dict"; 58 import {DICT_TYPE, getDictDatas} from "@/utils/dict";
65 import {getForm} from "@/api/bpm/form"; 59 import {getForm} from "@/api/bpm/form";
66 import {decodeFields} from "@/utils/formGenerator"; 60 import {decodeFields} from "@/utils/formGenerator";
67 import Parser from '@/components/parser/Parser' 61 import Parser from '@/components/parser/Parser'
  62 +import {createProcessInstance} from "@/api/bpm/processInstance";
68 63
69 export default { 64 export default {
70 name: "processDefinition", 65 name: "processDefinition",
@@ -79,49 +74,51 @@ export default { @@ -79,49 +74,51 @@ export default {
79 total: 0, 74 total: 0,
80 // 表格数据 75 // 表格数据
81 list: [], 76 list: [],
82 - // 查询参数  
83 - queryParams: {  
84 - pageNo: 1,  
85 - pageSize: 10  
86 - },  
87 77
88 // 流程表单详情 78 // 流程表单详情
89 - detailOpen: false,  
90 detailForm: { 79 detailForm: {
91 fields: [] 80 fields: []
92 }, 81 },
93 82
94 // BPMN 数据 83 // BPMN 数据
95 - showBpmnOpen: false,  
96 bpmnXML: null, 84 bpmnXML: null,
97 bpmnControlForm: { 85 bpmnControlForm: {
98 prefix: "activiti" 86 prefix: "activiti"
99 }, 87 },
100 88
  89 + // 流程表单
  90 + selectProcessInstance: undefined, // 选择的流程实例
  91 +
101 // 数据字典 92 // 数据字典
102 categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY), 93 categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
103 }; 94 };
104 }, 95 },
105 created() { 96 created() {
106 - const key = this.$route.query && this.$route.query.key  
107 - if (key) {  
108 - this.queryParams['key'] = key  
109 - }  
110 this.getList(); 97 this.getList();
111 }, 98 },
112 methods: { 99 methods: {
113 /** 查询流程定义列表 */ 100 /** 查询流程定义列表 */
114 getList() { 101 getList() {
115 this.loading = true; 102 this.loading = true;
116 - getProcessDefinitionPage(this.queryParams).then(response => {  
117 - this.list = response.data.list;  
118 - this.total = response.data.total;  
119 - this.loading = false; 103 + getProcessDefinitionList({
  104 + suspensionState: 1
  105 + }).then(response => {
  106 + this.list = response.data
  107 + this.loading = false
120 } 108 }
121 ); 109 );
122 }, 110 },
123 - /** 流程表单的详情按钮操作 */  
124 - handleFormDetail(row) { 111 + /** 处理选择流程的按钮操作 **/
  112 + handleSelect(row) {
  113 + // 如果无表单,则无法发起流程
  114 + if (!row.formId) {
  115 + this.$message.error('该流程未绑定表单,无法发起流程!请重新选择你要发起的流程');
  116 + return;
  117 + }
  118 + // 设置选择的流程
  119 + this.selectProcessInstance = row;
  120 +
  121 + // 加载对应的表单
125 getForm(row.formId).then(response => { 122 getForm(row.formId).then(response => {
126 // 设置值 123 // 设置值
127 const data = response.data 124 const data = response.data
@@ -129,16 +126,36 @@ export default { @@ -129,16 +126,36 @@ export default {
129 ...JSON.parse(data.conf), 126 ...JSON.parse(data.conf),
130 fields: decodeFields(data.fields) 127 fields: decodeFields(data.fields)
131 } 128 }
132 - // 弹窗打开  
133 - this.detailOpen = true  
134 - })  
135 - },  
136 - /** 流程图的详情按钮操作 */  
137 - handleBpmnDetail(row) { 129 + });
  130 +
  131 + // 加载流程图
138 getProcessDefinitionBpmnXML(row.id).then(response => { 132 getProcessDefinitionBpmnXML(row.id).then(response => {
139 this.bpmnXML = response.data 133 this.bpmnXML = response.data
140 - // 弹窗打开  
141 - this.showBpmnOpen = true 134 + })
  135 + },
  136 + /** 提交按钮 */
  137 + submitForm(params) {
  138 + if (!params) {
  139 + return;
  140 + }
  141 + // 设置表单禁用
  142 + const conf = params.conf;
  143 + conf.disabled = true; // 表单禁用
  144 + conf.formBtns = false; // 按钮隐藏
  145 +
  146 + // 提交表单,创建流程
  147 + const variables = params.values;
  148 + createProcessInstance({
  149 + processDefinitionId: this.selectProcessInstance.id,
  150 + variables: variables
  151 + }).then(response => {
  152 + this.msgSuccess("发起流程成功");
  153 + // 关闭当前窗口
  154 + this.$store.dispatch("tagsView/delView", this.$route);
  155 + this.$router.go(-1);
  156 + }).catch(() => {
  157 + conf.disabled = false; // 表单开启
  158 + conf.formBtns = true; // 按钮展示
142 }) 159 })
143 }, 160 },
144 } 161 }
@@ -149,4 +166,9 @@ export default { @@ -149,4 +166,9 @@ export default {
149 .my-process-designer { 166 .my-process-designer {
150 height: calc(100vh - 200px); 167 height: calc(100vh - 200px);
151 } 168 }
  169 +
  170 +.box-card {
  171 + width: 100%;
  172 + margin-bottom: 20px;
  173 +}
152 </style> 174 </style>
yudao-admin-ui/src/views/bpm/processInstance/index.vue
@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 47
48 <!-- 列表 --> 48 <!-- 列表 -->
49 <el-table v-loading="loading" :data="list"> 49 <el-table v-loading="loading" :data="list">
50 - <el-table-column label="编号" align="center" prop="id" width="300" /> 50 + <el-table-column label="编号" align="center" prop="id" width="320" />
51 <el-table-column label="流程名" align="center" prop="name" /> 51 <el-table-column label="流程名" align="center" prop="name" />
52 <el-table-column label="流程分类" align="center" prop="category"> 52 <el-table-column label="流程分类" align="center" prop="category">
53 <template slot-scope="scope"> 53 <template slot-scope="scope">