xm
2024-06-14 722af26bc6fec32bb289b1df51a9016a4935610f
提交 | 用户 | 时间
722af2 1 <template>
X 2   <div class="app-container">
3     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
4       <el-form-item label="模型标识" prop="modelKey">
5         <el-input
6           v-model="queryParams.modelKey"
7           placeholder="请输入模型标识"
8           clearable
9           size="small"
10           @keyup.enter.native="handleQuery"
11         />
12       </el-form-item>
13       <el-form-item label="模型名称" prop="modelName">
14         <el-input
15           v-model="queryParams.modelName"
16           placeholder="请输入模型名称"
17           clearable
18           size="small"
19           @keyup.enter.native="handleQuery"
20         />
21       </el-form-item>
22       <el-form-item label="流程分类" prop="category">
23         <el-select v-model="queryParams.category" clearable placeholder="请选择" size="small">
24           <el-option
25             v-for="item in categoryOptions"
26             :key="item.categoryId"
27             :label="item.categoryName"
28             :value="item.code">
29           </el-option>
30         </el-select>
31       </el-form-item>
32       <el-form-item>
33         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
34         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
35       </el-form-item>
36     </el-form>
37
38     <el-row :gutter="10" class="mb8">
39 <!--      <el-col :span="1.5">-->
40 <!--        <el-button-->
41 <!--          type="primary"-->
42 <!--          plain-->
43 <!--          icon="el-icon-upload"-->
44 <!--          size="mini"-->
45 <!--          @click="handleImport"-->
46 <!--          v-hasPermi="['workflow:model:import']"-->
47 <!--        >导入</el-button>-->
48 <!--      </el-col>-->
49       <el-col :span="1.5">
50         <el-button
51           type="success"
52           plain
53           icon="el-icon-plus"
54           size="mini"
55           @click="handleAdd"
56           v-hasPermi="['workflow:model:add']"
57         >新增</el-button>
58       </el-col>
59       <el-col :span="1.5">
60         <el-button
61           type="danger"
62           plain
63           icon="el-icon-delete"
64           size="mini"
65           :disabled="multiple"
66           @click="handleDelete"
67           v-hasPermi="['workflow:model:remove']"
68         >删除</el-button>
69       </el-col>
70       <el-col :span="1.5">
71         <el-button
72           type="warning"
73           plain
74           icon="el-icon-download"
75           size="mini"
76           @click="handleExport"
77           v-hasPermi="['workflow:model:export']"
78         >导出</el-button>
79       </el-col>
80       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
81     </el-row>
82
83     <el-table v-loading="loading" fit :data="modelList" @selection-change="handleSelectionChange">
84       <el-table-column type="selection" width="55" align="center" />
85       <el-table-column label="模型标识" align="center" prop="modelKey" :show-overflow-tooltip="true" />
86       <el-table-column label="模型名称" align="center" :show-overflow-tooltip="true">
87         <template slot-scope="scope">
88           <el-button type="text" @click="handleProcessView(scope.row)">
89             <span>{{ scope.row.modelName }}</span>
90           </el-button>
91         </template>
92       </el-table-column>
93       <el-table-column label="流程分类" align="center" prop="categoryName" :formatter="categoryFormat" />
94       <el-table-column label="模型版本" align="center">
95         <template slot-scope="scope">
96           <el-tag size="medium" >v{{ scope.row.version }}</el-tag>
97         </template>
98       </el-table-column>
99       <el-table-column label="描述" align="center" prop="description" :show-overflow-tooltip="true" />
100       <el-table-column label="创建时间" align="center" prop="createTime" width="180"/>
101       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
102         <template slot-scope="scope">
103           <el-button
104             size="mini"
105             type="text"
106             icon="el-icon-edit"
107             @click="handleUpdate(scope.row)"
108             v-hasPermi="['workflow:model:edit']"
109           >修改</el-button>
110           <el-button
111             type="text"
112             size="mini"
113             icon="el-icon-brush"
114             @click="handleDesigner(scope.row)"
115             v-hasPermi="['workflow:model:designer']"
116           >设计</el-button>
117           <el-button
118             type="text"
119             size="mini"
120             icon="el-icon-video-play"
121             v-hasPermi="['workflow:model:deploy']"
122             @click.native="handleDeploy(scope.row)"
123           >部署</el-button>
124           <el-dropdown size="mini" v-hasPermi="['workflow:model:query', 'workflow:model:list', 'workflow:model:remove']">
125             <el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
126             <el-dropdown-menu slot="dropdown">
127               <el-dropdown-item
128                 icon="el-icon-view"
129                 @click.native="handleProcessView(scope.row)"
130                 v-hasPermi="['workflow:model:query']"
131               >流程图</el-dropdown-item>
132               <el-dropdown-item
133                 icon="el-icon-price-tag"
134                 @click.native="handleHistory(scope.row)"
135                 v-hasPermi="['workflow:model:list']"
136               >历史</el-dropdown-item>
137               <el-dropdown-item
138                 icon="el-icon-delete"
139                 @click.native="handleDelete(scope.row)"
140                 v-hasPermi="['workflow:model:remove']"
141               >删除</el-dropdown-item>
142             </el-dropdown-menu>
143           </el-dropdown>
144         </template>
145       </el-table-column>
146     </el-table>
147
148     <pagination
149       v-show="total > 0"
150       :total="total"
151       :page.sync="queryParams.pageNum"
152       :limit.sync="queryParams.pageSize"
153       @pagination="getList"
154     />
155
156     <!--  添加或修改模型信息对话框  -->
157     <el-dialog :title="title" :visible.sync="open" width="30%" append-to-body @close="cancel()">
158       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
159         <el-form-item label="模型标识" prop="modelKey">
160           <el-input v-model="form.modelKey" clearable disabled />
161         </el-form-item>
162         <el-form-item label="模型名称" prop="modelName">
163           <el-input v-model="form.modelName" clearable :disabled="form.modelId !== undefined" />
164         </el-form-item>
165         <el-form-item label="流程分类" prop="category">
166           <el-select v-model="form.category" placeholder="请选择" clearable style="width:100%">
167             <el-option v-for="item in categoryOptions" :key="item.categoryId" :label="item.categoryName" :value="item.code" />
168           </el-select>
169         </el-form-item>
170         <el-form-item label="描述" prop="description">
171           <el-input v-model="form.description" type="textarea" placeholder="请输入内容" maxlength="200" show-word-limit/>
172         </el-form-item>
173       </el-form>
174       <div slot="footer" class="dialog-footer">
175         <el-button type="primary" @click="submitForm">确 定</el-button>
176         <el-button @click="cancel()">取 消</el-button>
177       </div>
178     </el-dialog>
179
180
181   <!--  &lt;!&ndash; bpmn20.xml导入对话框 &ndash;&gt;-->
182   <!--  <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body @close="cancel('uploadForm')">-->
183   <!--    <el-upload-->
184   <!--      ref="upload"-->
185   <!--      :limit="1"-->
186   <!--      accept=".xml"-->
187   <!--      :headers="upload.headers"-->
188   <!--      :action="upload.url + '?name=' + upload.name+'&category='+ upload.category"-->
189   <!--      :disabled="upload.isUploading"-->
190   <!--      :on-progress="handleFileUploadProgress"-->
191   <!--      :on-success="handleFileSuccess"-->
192   <!--      :auto-upload="false"-->
193   <!--      drag-->
194   <!--    >-->
195   <!--      <i class="el-icon-upload"></i>-->
196   <!--      <div class="el-upload__text">-->
197   <!--        将文件拖到此处,或-->
198   <!--        <em>点击上传</em>-->
199   <!--      </div>-->
200   <!--      <div class="el-upload__tip" slot="tip">-->
201   <!--        <el-form ref="uploadForm" :model="upload" size="mini" :rules="rules" label-width="80px">-->
202   <!--          <el-form-item label="流程名称" prop="name">-->
203   <!--            <el-input v-model="upload.name" clearable/>-->
204   <!--          </el-form-item>-->
205   <!--          <el-form-item label="流程分类" prop="category">-->
206   <!--            <el-select v-model="upload.category" placeholder="请选择" clearable style="width:100%">-->
207   <!--              <el-option v-for="item in categoryOptions" :key="item.categoryId" :label="item.categoryName"-->
208   <!--                         :value="item.code"/>-->
209   <!--            </el-select>-->
210   <!--          </el-form-item>-->
211   <!--        </el-form>-->
212   <!--      </div>-->
213   <!--      <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“bpmn20.xml”格式文件!</div>-->
214   <!--    </el-upload>-->
215   <!--    <div slot="footer" class="dialog-footer">-->
216   <!--      <el-button type="primary" @click="submitFileForm">确 定</el-button>-->
217   <!--      <el-button @click="cancel('uploadForm')">取 消</el-button>-->
218   <!--    </div>-->
219   <!--  </el-dialog>-->
220
221     <!-- 流程图 -->
222     <el-dialog :title="processView.title" :visible.sync="processView.open" width="70%" append-to-body>
223       <process-viewer :key="`designer-${processView.index}`" :xml="processView.xmlData" :style="{height: '400px'}" />
224     </el-dialog>
225
226     <el-dialog title="模型历史" :visible.sync="history.open" width="70%" >
227       <el-table v-loading="history.loading" fit :data="historyList" @selection-change="handleSelectionChange">
228         <el-table-column type="selection" width="55" align="center" />
229         <el-table-column label="模型标识" align="center" prop="modelKey" :show-overflow-tooltip="true" />
230         <el-table-column label="模型名称" align="center" :show-overflow-tooltip="true">
231           <template slot-scope="scope">
232             <el-button type="text" @click="handleProcessView(scope.row)">
233               <span>{{ scope.row.modelName }}</span>
234             </el-button>
235           </template>
236         </el-table-column>
237         <el-table-column label="流程分类" align="center" prop="categoryName" :formatter="categoryFormat" />
238         <el-table-column label="模型版本" align="center">
239           <template slot-scope="scope">
240             <el-tag size="medium" >v{{ scope.row.version }}</el-tag>
241           </template>
242         </el-table-column>
243         <el-table-column label="描述" align="center" prop="description" :show-overflow-tooltip="true" />
244         <el-table-column label="创建时间" align="center" prop="createTime" width="180"/>
245         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
246           <template slot-scope="scope">
247             <el-button
248               type="text"
249               size="mini"
250               icon="el-icon-video-play"
251               v-hasPermi="['workflow:model:deploy']"
252               @click.native="handleDeploy(scope.row)"
253             >部署</el-button>
254             <el-button
255               type="text"
256               size="mini"
257               icon="el-icon-star-off"
258               v-hasPermi="['workflow:model:save']"
259               @click.native="handleLatest(scope.row)"
260             >设为最新</el-button>
261           </template>
262         </el-table-column>
263       </el-table>
264
265       <pagination
266         v-show="historyTotal > 0"
267         :total="historyTotal"
268         :page.sync="queryHistoryParams.pageNum"
269         :limit.sync="queryHistoryParams.pageSize"
270         @pagination="getHistoryList"
271       />
272     </el-dialog>
273
274     <el-dialog :title="designerData.title" :visible.sync="designerOpen" append-to-body fullscreen>
275       <process-designer
276         :key="designerOpen"
277         style="border:1px solid rgba(0, 0, 0, 0.1);"
278         ref="modelDesigner"
279         v-loading="designerData.loading"
280         :bpmnXml="designerData.bpmnXml"
281         :designerForm="designerData.form"
282         @save="onSaveDesigner"
283       />
284     </el-dialog>
285   </div>
286
287 </template>
288
289 <script>
290 import { getBpmnXml, listModel, historyModel, latestModel, addModel, updateModel, saveModel, delModel, deployModel } from "@/api/workflow/model";
291 import { listCategory } from '@/api/workflow/category'
292 import ProcessDesigner from '@/components/ProcessDesigner';
293 import ProcessViewer from '@/components/ProcessViewer'
294 import { getToken } from "@/utils/auth";
295
296 export default {
297   name: "Model",
298   components: {
299     ProcessDesigner,
300     ProcessViewer,
301   },
302   data() {
303     return {
304       // 遮罩层
305       loading: true,
306       // 选中数组
307       ids: [],
308       // 非单个禁用
309       single: true,
310       // 非多个禁用
311       multiple: true,
312       // 显示搜索条件
313       showSearch: true,
314       // 总条数
315       total: 0,
316       // 流程模型表格数据
317       modelList: [],
318       categoryOptions: [],
319       title: '',
320       open: false,
321       form: {},
322       // 表单校验
323       rules: {
324         modelKey: [
325           { required: true, message: "模型标识不能为空", trigger: "blur" }
326         ],
327         modelName: [
328           { required: true, message: "模型名称不能为空", trigger: "blur" }
329         ],
330         category: [
331           { required: true, message: "请选择类型", trigger: "change" }
332         ],
333       },
334       designerOpen: false,
335       designerData: {
336         loading: false,
337         bpmnXml: '',
338         modelId: null,
339         form: {
340           processName: null,
341           processKey: null
342         }
343       },
344       designerModelId: null,
345       processView: {
346         title: '',
347         open: false,
348         index: undefined,
349         xmlData:"",
350       },
351       // bpmn.xml 导入
352       upload: {
353         // 是否显示弹出层(xml导入)
354         open: false,
355         // 弹出层标题(xml导入)
356         title: "",
357         // 是否禁用上传
358         isUploading: false,
359         name: null,
360         category: null,
361         // 设置上传的请求头部
362         headers: { Authorization: "Bearer " + getToken() },
363         // 上传的地址
364         url: process.env.VUE_APP_BASE_API + "/workflow/definition/import"
365       },
366       // 查询参数
367       queryParams: {
368         pageNum: 1,
369         pageSize: 10,
370         modelKey: null,
371         modelName: null,
372         category: null
373       },
374       currentRow: null,
375       history: {
376         open: false,
377         loading: false
378       },
379       historyList: [],
380       historyTotal: 0,
381       queryHistoryParams: {
382         pageNum: 1,
383         pageSize: 10,
384         modelKey: null
385       }
386     };
387   },
388   created() {
389     this.getCategoryList();
390     this.getList();
391   },
392   methods: {
393     /** 查询流程分类列表 */
394     getCategoryList() {
395       listCategory().then(response => this.categoryOptions = response.rows)
396     },
397     /** 查询流程模型列表 */
398     getList() {
399       this.loading = true;
400       listModel(this.queryParams).then(response => {
401         this.modelList = response.rows;
402         this.total = response.total;
403         this.loading = false;
404       });
405     },
406     cancel() {
407       this.reset();
408       // 关闭dialog
409       this.open = false
410     },
411     // 表单重置
412     reset() {
413       this.form = {
414         modelId: undefined,
415         modelKey: undefined,
416         modelName: undefined,
417         category: undefined,
418         description: undefined
419       };
420     },
421     /** 搜索按钮操作 */
422     handleQuery() {
423       this.queryParams.pageNum = 1;
424       this.getList();
425     },
426     /** 重置按钮操作 */
427     resetQuery() {
428       this.$refs.queryForm.resetFields()
429       this.handleQuery();
430     },
431     // 多选框选中数据
432     handleSelectionChange(selection) {
433       this.ids = selection.map(item => item.modelId)
434       this.single = selection.length !== 1
435       this.multiple = !selection.length
436     },
437     /** 部署流程 */
438     handleDeploy(row) {
439       this.loading = true;
440       deployModel({
441         modelId: row.modelId
442       }).then(response => {
443         this.$modal.msgSuccess(response.msg);
444         let obj = { name: 'Deploy', path: '/workflow/deploy' }
445         return this.$store.dispatch('tagsView/delCachedView', obj).then(() => {
446           this.$router.push(obj);
447         });
448       }).finally(() => {
449         this.loading = false;
450       })
451     },
452     /** 查看流程图 */
453     handleProcessView(row) {
454       let modelId = row.modelId;
455       this.processView.title = "流程图";
456       this.processView.index = modelId;
457       // 发送请求,获取xml
458       getBpmnXml(modelId).then(response => {
459         this.processView.xmlData = response.data;
460       })
461       this.processView.open = true;
462     },
463     getHistoryList() {
464       this.history.loading = true;
465       historyModel(this.queryHistoryParams).then(response => {
466         this.historyTotal = response.total;
467         this.historyList = response.rows;
468         this.history.loading = false;
469       })
470     },
471     handleHistory(row) {
472       this.history.open = true;
473       this.queryHistoryParams.modelKey = row.modelKey;
474       this.getHistoryList();
475     },
476     /** 设为最新版 */
477     handleLatest(row) {
478       this.$modal.confirm('是否确认将此版本设为最新?').then(() => {
479         this.history.loading = true;
480         latestModel({
481           modelId: row.modelId
482         }).then(response => {
483           this.history.open = false;
484           this.getList();
485           this.$modal.msgSuccess(response.msg);
486         }).finally(() => {
487           this.history.loading = false;
488         })
489       })
490     },
491     handleCurrentChange(data) {
492       if (data) {
493         this.currentRow = JSON.parse(data.content);
494       }
495     },
496     handleAdd() {
497       this.title = "新增流程模型";
498       const dateTime = new Date().getTime();
499       this.form = {
500         modelKey: `Process_${dateTime}`,
501         modelName: `业务流程_${dateTime}`
502       }
503       this.open = true;
504     },
505     /** 修改按钮操作 */
506     handleUpdate(row) {
507       this.title = "修改流程模型";
508       this.form = {
509         modelId: row.modelId,
510         modelKey: row.modelKey,
511         modelName: row.modelName,
512         category: row.category,
513         description: row.description
514       };
515       this.open = true;
516     },
517     submitForm() {
518       this.$refs["form"].validate(valid => {
519         if (valid) {
520           if (this.form.modelId !== undefined) {
521             updateModel(this.form).then(response => {
522               this.$modal.msgSuccess("修改成功");
523               this.open = false;
524               this.getList();
525             });
526           } else {
527             addModel(this.form).then(response => {
528               this.$modal.msgSuccess("新增成功");
529               this.open = false;
530               this.getList();
531             });
532           }
533         }
534       });
535     },
536     /** 设计按钮操作 */
537     handleDesigner(row) {
538       this.designerData.title = "流程设计 - " + row.modelName;
539       this.designerData.modelId = row.modelId;
540       this.designerData.form = {
541         processName: row.modelName,
542         processKey: row.modelKey
543       }
544       if (row.modelId) {
545         this.designerData.loading = true;
546         getBpmnXml(row.modelId).then(response => {
547           this.designerData.bpmnXml = response.data || '';
548           this.designerData.loading = false;
549           this.designerOpen = true;
550         })
551       }
552     },
553     onSaveDesigner(bpmnXml) {
554       this.bpmnXml = bpmnXml;
555       let dataBody = {
556         modelId: this.designerData.modelId,
557         bpmnXml: this.bpmnXml
558       }
559       this.$confirm("是否将此模型保存为新版本?", "提示", {
560         distinguishCancelAndClose: true,
561         confirmButtonText: '是',
562         cancelButtonText: '否'
563       }).then(() => {
564         this.confirmSave(dataBody, true)
565       }).catch(action => {
566         if (action === 'cancel') {
567           this.confirmSave(dataBody, false)
568         }
569       })
570     },
571     confirmSave(body, newVersion) {
572       this.designerData.loading = true;
573       saveModel(Object.assign(body, {
574         newVersion: newVersion
575       })).then(() => {
576         this.designerOpen = false;
577         this.getList();
578       }).finally(() => {
579         this.designerData.loading = false;
580       })
581     },
582     /** 删除按钮操作 */
583     handleDelete(row) {
584       const modelIds = row.modelId || this.ids;
585       this.$modal.confirm('是否确认删除模型编号为"' + modelIds + '"的数据项?').then(() => {
586         this.loading = true;
587         return delModel(modelIds);
588       }).then(() => {
589         this.loading = false;
590         this.getList();
591         this.$modal.msgSuccess("删除成功");
592       }).finally(() => {
593         this.loading = false;
594       });
595     },
596     /** 导出按钮操作 */
597     handleExport() {
598       this.download('workflow/model/export', {
599         ...this.queryParams
600       }, `wf_model_${new Date().getTime()}.xlsx`)
601     },
602     /** 导入bpmn.xml文件 */
603     handleImport() {
604       this.upload.title = "bpmn20.xml文件导入";
605       this.upload.open = true;
606     },
607     // 文件上传中处理
608     handleFileUploadProgress(event, file, fileList) {
609       this.upload.isUploading = true;
610     },
611     // 文件上传成功处理
612     handleFileSuccess(response, file, fileList) {
613       this.upload.open = false;
614       this.upload.isUploading = false;
615       this.$refs.upload.clearFiles();
616       this.$message.success(response.msg);
617       this.getList();
618     },
619     // 提交上传文件
620     submitFileForm() {
621       this.$refs.uploadForm.validate(valid => {
622         if (valid) {
623           this.$refs.upload.submit();
624         }
625       });
626     },
627     categoryFormat(row, column) {
628       return this.categoryOptions.find(k => k.code === row.category)?.categoryName ?? '';
629     },
630     submitSave() {
631       this.getList();
632     }
633   }
634 };
635 </script>