Commit cfbef058b5c39500f82b2947a404a5afbda4e59a

Authored by YunaiV
1 parent ed33ff9f

完成流程图上传的功能

yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/ProcessDefinitionController.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmDefinitionController.java
... ... @@ -22,7 +22,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
22 22 @RestController
23 23 @RequestMapping("/bpm/definition")
24 24 @Validated
25   -public class ProcessDefinitionController {
  25 +public class BpmDefinitionController {
26 26  
27 27 @Resource
28 28 private BpmDefinitionService bpmDefinitionService;
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/model/BpmModelController.java
1 1 package cn.iocoder.yudao.adminserver.modules.bpm.controller.model;
2 2  
3 3 import cn.iocoder.yudao.adminserver.modules.bpm.controller.model.vo.*;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.convert.model.BpmModelConvert;
4 5 import cn.iocoder.yudao.adminserver.modules.bpm.service.model.BpmModelService;
5 6 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  8 +import cn.iocoder.yudao.framework.common.util.io.IoUtils;
7 9 import io.swagger.annotations.Api;
8 10 import io.swagger.annotations.ApiImplicitParam;
9 11 import io.swagger.annotations.ApiOperation;
... ... @@ -11,6 +13,7 @@ import org.springframework.validation.annotation.Validated;
11 13 import org.springframework.web.bind.annotation.*;
12 14  
13 15 import javax.annotation.Resource;
  16 +import java.io.IOException;
14 17  
15 18 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
16 19  
... ... @@ -23,7 +26,7 @@ public class BpmModelController {
23 26 @Resource
24 27 private BpmModelService bpmModelService;
25 28  
26   - // TODO @芋艿:权限
  29 + // TODO @芋艿:权限、参数校验
27 30  
28 31 @GetMapping("/page")
29 32 @ApiOperation(value = "获得模型分页")
... ... @@ -46,6 +49,15 @@ public class BpmModelController {
46 49 return success(bpmModelService.createModel(createRetVO));
47 50 }
48 51  
  52 + @PostMapping("/import")
  53 + @ApiOperation(value = "导入模型")
  54 + public CommonResult<String> importModel(BpmModeImportReqVO importReqVO) throws IOException {
  55 + BpmModelCreateReqVO createReqVO = BpmModelConvert.INSTANCE.convert(importReqVO);
  56 + // 读取文件
  57 + createReqVO.setBpmnXml(IoUtils.readUtf8(importReqVO.getBpmnFile().getInputStream(), false));
  58 + return success(bpmModelService.createModel(createReqVO));
  59 + }
  60 +
49 61 @PutMapping("/update")
50 62 @ApiOperation(value = "修改模型")
51 63 public CommonResult<Boolean> updateModel(@RequestBody BpmModelUpdateReqVO modelVO) {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/model/vo/BpmModeImportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.model.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +import org.springframework.web.multipart.MultipartFile;
  9 +
  10 +import javax.validation.constraints.NotNull;
  11 +
  12 +@ApiModel("流程模型的导入 Request VO")
  13 +@Data
  14 +@EqualsAndHashCode(callSuper = true)
  15 +@ToString(callSuper = true)
  16 +public class BpmModeImportReqVO extends BpmModelBaseVO {
  17 +
  18 + @ApiModelProperty(value = "BPMN 文件", required = true)
  19 + @NotNull(message = "BPMN 文件不能为空")
  20 + private MultipartFile bpmnFile;
  21 +
  22 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/model/ModelConvert.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/model/BpmModelConvert.java
1 1 package cn.iocoder.yudao.adminserver.modules.bpm.convert.model;
2 2  
3   -import cn.iocoder.yudao.adminserver.modules.bpm.controller.model.vo.BpmModelCreateReqVO;
4   -import cn.iocoder.yudao.adminserver.modules.bpm.controller.model.vo.BpmModelPageItemRespVO;
5   -import cn.iocoder.yudao.adminserver.modules.bpm.controller.model.vo.BpmModelRespVO;
6   -import cn.iocoder.yudao.adminserver.modules.bpm.controller.model.vo.BpmModelUpdateReqVO;
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.model.vo.*;
7 4 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO;
8 5 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
9 6 import cn.iocoder.yudao.adminserver.modules.bpm.service.model.dto.BpmModelMetaInfoRespDTO;
... ... @@ -26,9 +23,9 @@ import java.util.Map;
26 23 * @author yunlongn
27 24 */
28 25 @Mapper
29   -public interface ModelConvert {
  26 +public interface BpmModelConvert {
30 27  
31   - ModelConvert INSTANCE = Mappers.getMapper(ModelConvert.class);
  28 + BpmModelConvert INSTANCE = Mappers.getMapper(BpmModelConvert.class);
32 29  
33 30 default List<BpmModelPageItemRespVO> convertList(List<Model> list, Map<Long, BpmFormDO> formMap,
34 31 Map<String, Deployment> deploymentMap,
... ... @@ -116,4 +113,6 @@ public interface ModelConvert {
116 113  
117 114 BpmModelPageItemRespVO.ProcessDefinition convert(ProcessDefinition bean);
118 115  
  116 + BpmModelCreateReqVO convert(BpmModeImportReqVO bean);
  117 +
119 118 }
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/ProcessService.java deleted
1   -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition;
2   -
3   -import org.springframework.web.multipart.MultipartFile;
4   -
5   -/**
6   - * 流程基础管理
7   - *
8   - * @author ZJQ
9   - * @date 2021/9/5 21:00
10   - */
11   -@Deprecated
12   -public interface ProcessService {
13   -
14   - /**
15   - * 上传流程文件,进行流程模型部署
16   - * @param multipartFile 上传文件
17   - */
18   - void deployProcess(MultipartFile multipartFile);
19   -
20   -}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/ProcessServiceImpl.java deleted
1   -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition;
2   -
3   -import lombok.extern.slf4j.Slf4j;
4   -import org.activiti.engine.RepositoryService;
5   -import org.activiti.engine.repository.Deployment;
6   -import org.activiti.engine.repository.ProcessDefinition;
7   -import org.apache.commons.io.FilenameUtils;
8   -import org.springframework.stereotype.Service;
9   -import org.springframework.web.multipart.MultipartFile;
10   -
11   -import javax.annotation.Resource;
12   -import java.io.IOException;
13   -import java.io.InputStream;
14   -import java.util.List;
15   -import java.util.zip.ZipInputStream;
16   -
17   -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.FILE_UPLOAD_FAILED;
18   -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19   -
20   -/**
21   - * 流程基础管理
22   - *
23   - * @author ZJQ
24   - * @date 2021/9/5 21:04
25   - */
26   -@Service
27   -@Slf4j
28   -@Deprecated
29   -public class ProcessServiceImpl implements ProcessService {
30   -
31   - private static final String BPMN20_XML = "bpmn20.xml";
32   -
33   - @Resource
34   - private RepositoryService repositoryService;
35   -
36   - /**
37   - * 上传流程文件,进行流程部署
38   - * @param multipartFile 上传文件
39   - */
40   - @Override
41   - public void deployProcess(MultipartFile multipartFile) {
42   - String fileName = multipartFile.getOriginalFilename();
43   - try (InputStream inputStream = multipartFile.getInputStream()){
44   - Deployment deployment = getDeplymentByType(inputStream,fileName);
45   - //获取部署成功的流程模型
46   - List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
47   - processDefinitions.forEach((processDefinition)->{
48   - //设置线上部署流程模型名字
49   - String proDefId = processDefinition.getId();
50   - repositoryService.setProcessDefinitionCategory(proDefId,fileName);
51   - log.info("流程文件部署成功,流程ID="+proDefId);
52   - });
53   - } catch (IOException e) {
54   - log.error("流程部署出现异常"+e);
55   - }
56   - }
57   -
58   - /**
59   - * 根据上传文件类型对应实现不同方式的流程部署
60   - * @param inputStream 文件输入流
61   - * @param fileName 文件名
62   - * @return 文件部署流程
63   - */
64   - public Deployment getDeplymentByType(InputStream inputStream,String fileName){
65   - Deployment deployment;
66   - String type = FilenameUtils.getExtension(fileName);
67   - switch (type){
68   - case "bpmn":
69   - String baseName = FilenameUtils.getBaseName(fileName);
70   - deployment = repositoryService.createDeployment().addInputStream(baseName+"."+BPMN20_XML,inputStream).deploy();
71   - break;
72   - case "png":
73   - deployment = repositoryService.createDeployment().addInputStream(fileName,inputStream).deploy();
74   - break;
75   - case "zip":
76   - case "bar":
77   - ZipInputStream zipInputStream = new ZipInputStream(inputStream);
78   - deployment = repositoryService.createDeployment().addZipInputStream(zipInputStream).deploy();
79   - break;
80   - default:
81   - throw exception(FILE_UPLOAD_FAILED);
82   - }
83   - return deployment;
84   - }
85   -}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/model/impl/BpmModelServiceImpl.java
... ... @@ -2,7 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.model.impl;
2 2  
3 3 import cn.hutool.core.util.StrUtil;
4 4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.model.vo.*;
5   -import cn.iocoder.yudao.adminserver.modules.bpm.convert.model.ModelConvert;
  5 +import cn.iocoder.yudao.adminserver.modules.bpm.convert.model.BpmModelConvert;
6 6 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO;
7 7 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmDefinitionService;
8 8 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
... ... @@ -87,7 +87,7 @@ public class BpmModelServiceImpl implements BpmModelService {
87 87  
88 88 // 拼接结果
89 89 long modelCount = modelQuery.count();
90   - return new PageResult<>(ModelConvert.INSTANCE.convertList(models, formMap, deploymentMap, processDefinitionMap), modelCount);
  90 + return new PageResult<>(BpmModelConvert.INSTANCE.convertList(models, formMap, deploymentMap, processDefinitionMap), modelCount);
91 91 }
92 92  
93 93 @Override
... ... @@ -96,7 +96,7 @@ public class BpmModelServiceImpl implements BpmModelService {
96 96 if (model == null) {
97 97 return null;
98 98 }
99   - BpmModelRespVO modelRespVO = ModelConvert.INSTANCE.convert(model);
  99 + BpmModelRespVO modelRespVO = BpmModelConvert.INSTANCE.convert(model);
100 100 // 拼接 bpmn XML
101 101 byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
102 102 modelRespVO.setBpmnXml(StrUtil.utf8Str(bpmnBytes));
... ... @@ -115,7 +115,7 @@ public class BpmModelServiceImpl implements BpmModelService {
115 115  
116 116 // 创建流程定义
117 117 Model model = repositoryService.newModel();
118   - ModelConvert.INSTANCE.copy(model, createReqVO);
  118 + BpmModelConvert.INSTANCE.copy(model, createReqVO);
119 119 // 保存流程定义
120 120 repositoryService.saveModel(model);
121 121 // 添加 BPMN XML
... ... @@ -134,7 +134,7 @@ public class BpmModelServiceImpl implements BpmModelService {
134 134 }
135 135  
136 136 // 修改流程定义
137   - ModelConvert.INSTANCE.copy(model, updateReqVO);
  137 + BpmModelConvert.INSTANCE.copy(model, updateReqVO);
138 138 // 更新模型
139 139 repositoryService.saveModel(model);
140 140 // 更新 BPMN XML
... ... @@ -155,7 +155,7 @@ public class BpmModelServiceImpl implements BpmModelService {
155 155 }
156 156  
157 157 // 创建流程定义
158   - BpmDefinitionCreateReqDTO definitionCreateReqDTO = ModelConvert.INSTANCE.convert2(model)
  158 + BpmDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model)
159 159 .setBpmnXml(StrUtil.utf8Str(bpmnBytes));
160 160 String definitionId = bpmDefinitionService.createDefinition(definitionCreateReqDTO);
161 161  
... ...
yudao-admin-ui/src/utils/request.js
... ... @@ -121,4 +121,11 @@ service.interceptors.response.use(res =&gt; {
121 121 }
122 122 )
123 123  
  124 +export function getBaseHeader() {
  125 + return {
  126 + 'Authorization': "Bearer " + getToken(),
  127 + 'tenant-id': Cookies.get('tenantId'),
  128 + }
  129 +}
  130 +
124 131 export default service
... ...
yudao-admin-ui/src/views/bpm/model/index.vue
... ... @@ -28,6 +28,10 @@
28 28 <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
29 29 v-hasPermi="['infra:config:create']">新建流程模型</el-button>
30 30 </el-col>
  31 + <el-col :span="1.5">
  32 + <el-button type="info" icon="el-icon-upload2" size="mini" @click="handleImport"
  33 + v-hasPermi="['system:user:import']">导入流程模型</el-button>
  34 + </el-col>
31 35 <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
32 36 </el-row>
33 37  
... ... @@ -100,15 +104,75 @@
100 104 <el-dialog title="流程图" :visible.sync="showBpmnOpen" width="80%" append-to-body>
101 105 <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
102 106 </el-dialog>
  107 +
  108 + <!-- 用户导入对话框 -->
  109 + <el-dialog title="导入流程模型" :visible.sync="upload.open" width="400px" append-to-body>
  110 + <el-upload
  111 + ref="upload"
  112 + :limit="1"
  113 + accept=".bpmn, .xml"
  114 + :headers="upload.headers"
  115 + :action="upload.url"
  116 + :disabled="upload.isUploading"
  117 + :on-progress="handleFileUploadProgress"
  118 + :on-success="handleFileSuccess"
  119 + :auto-upload="false"
  120 + name="bpmnFile"
  121 + :data="upload.form"
  122 + drag
  123 + >
  124 + <i class="el-icon-upload"></i>
  125 + <div class="el-upload__text">
  126 + 将文件拖到此处,或
  127 + <em>点击上传</em>
  128 + </div>
  129 + <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“bpm”或“xml”格式文件!</div>
  130 +
  131 + <!-- <div class="el-upload__tip" slot="tip">-->
  132 +<!-- 流程名称:<el-input v-model="upload.name"/>-->
  133 +<!-- 流程分类:<el-input v-model="upload.category"/>-->
  134 +<!-- </div>-->
  135 + <div class="el-upload__tip" slot="tip">
  136 + <el-form ref="uploadForm" size="mini" label-width="90px" :model="upload.form" :rules="upload.rules" @submit.native.prevent>
  137 + <el-form-item label="流程标识" prop="key">
  138 + <el-input v-model="upload.form.key" placeholder="请输入流标标识" />
  139 + </el-form-item>
  140 + <el-form-item label="流程名称" prop="name">
  141 + <el-input v-model="upload.form.name" placeholder="请输入流程名称" clearable />
  142 + </el-form-item>
  143 + <el-form-item label="流程分类" prop="category">
  144 + <el-select v-model="upload.form.category" placeholder="请选择流程分类" clearable style="width: 100%">
  145 + <el-option v-for="dict in categoryDictDatas" :key="dict.value" :label="dict.label" :value="dict.value"/>
  146 + </el-select>
  147 + </el-form-item>
  148 + <el-form-item label="流程表单" prop="formId">
  149 + <el-select v-model="upload.form.formId" placeholder="请选择流程表单,非必选哟!" clearable style="width: 100%">
  150 + <el-option v-for="form in forms" :key="form.id" :label="form.name" :value="form.id"/>
  151 + </el-select>
  152 + </el-form-item>
  153 + <el-form-item label="流程描述" prop="description">
  154 + <el-input type="textarea" v-model="upload.form.description" clearable />
  155 + </el-form-item>
  156 + </el-form>
  157 + </div>
  158 + </el-upload>
  159 + <div slot="footer" class="dialog-footer">
  160 + <el-button type="primary" @click="submitFileForm">确 定</el-button>
  161 + <el-button @click="uploadClose">取 消</el-button>
  162 + </div>
  163 + </el-dialog>
103 164 </div>
104 165 </template>
105 166  
106 167 <script>
107 168 import {deleteModel, deployModel, getModelPage, getModel, updateModelState} from "@/api/bpm/model";
108 169 import {DICT_TYPE, getDictDatas} from "@/utils/dict";
109   -import {getForm} from "@/api/bpm/form";
  170 +import {getForm, getSimpleForms} from "@/api/bpm/form";
110 171 import {decodeFields} from "@/utils/formGenerator";
111 172 import Parser from '@/components/parser/Parser'
  173 +import {getToken} from "@/utils/auth";
  174 +import {getBaseHeader} from "@/utils/request";
  175 +import {addUser, updateUser} from "@/api/system/user";
112 176  
113 177 export default {
114 178 name: "model",
... ... @@ -144,12 +208,38 @@ export default {
144 208 fields: []
145 209 },
146 210  
  211 + // 流程导入参数
  212 + upload: {
  213 + // 是否显示弹出层(用户导入)
  214 + open: false,
  215 + // 是否禁用上传
  216 + isUploading: false,
  217 + // 设置上传的请求头部
  218 + headers: getBaseHeader(),
  219 + // 上传的地址
  220 + url: process.env.VUE_APP_BASE_API + '/api/' + "/bpm/model/import",
  221 + // 表单
  222 + form: {},
  223 + // 校验规则
  224 + rules: {
  225 + key: [{ required: true, message: "流程标识不能为空", trigger: "blur" }],
  226 + name: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
  227 + category: [{ required: true, message: "流程分类不能为空", trigger: "blur" }],
  228 + },
  229 + },
  230 + // 流程表单的下拉框的数据
  231 + forms: [],
  232 +
147 233 // 数据字典
148 234 categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
149 235 };
150 236 },
151 237 created() {
152 238 this.getList();
  239 + // 获得流程表单的下拉框的数据
  240 + getSimpleForms().then(response => {
  241 + this.forms = response.data
  242 + })
153 243 },
154 244 methods: {
155 245 /** 查询流程模型列表 */
... ... @@ -267,6 +357,45 @@ export default {
267 357 this.msgSuccess(statusState + "成功");
268 358 })
269 359 },
  360 + /** 导入按钮操作 */
  361 + handleImport() {
  362 + this.upload.open = true;
  363 + },
  364 + // 文件上传中处理
  365 + handleFileUploadProgress(event, file, fileList) {
  366 + this.upload.isUploading = true;
  367 + },
  368 + // 文件上传成功处理
  369 + handleFileSuccess(response, file, fileList) {
  370 + if (response.code !== 0) {
  371 + this.msgError(response.msg)
  372 + return;
  373 + }
  374 + // 重置表单
  375 + this.uploadClose();
  376 + // 提示,并刷新
  377 + this.msgSuccess("上传成功!请点击【设计流程】按钮,进行编辑保存后,才可以进行【发布流程】");
  378 + this.getList();
  379 + },
  380 + uploadClose() {
  381 + // 关闭弹窗
  382 + this.upload.open = false;
  383 + // 重置上传状态和文件
  384 + this.upload.isUploading = false;
  385 + this.$refs.upload.clearFiles();
  386 + // 重置表单
  387 + this.upload.form = {};
  388 + this.resetForm("uploadForm");
  389 + },
  390 + /** 提交上传文件 */
  391 + submitFileForm() {
  392 + this.$refs["uploadForm"].validate(valid => {
  393 + if (!valid) {
  394 + return;
  395 + }
  396 + this.$refs.upload.submit();
  397 + })
  398 + },
270 399 }
271 400 };
272 401 </script>
... ...
yudao-admin-ui/src/views/bpm/model/modelEditor.vue
... ... @@ -61,6 +61,7 @@ export default {
61 61 ...response.data,
62 62 bpmnXml: undefined, // 清空 bpmnXml 属性
63 63 }
  64 + // this.controlForm.processId = response.data.key
64 65 })
65 66 }
66 67 },
... ...
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/io/IoUtils.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.common.util.io;
  2 +
  3 +import cn.hutool.core.io.IORuntimeException;
  4 +import cn.hutool.core.io.IoUtil;
  5 +import cn.hutool.core.util.CharsetUtil;
  6 +import cn.hutool.core.util.StrUtil;
  7 +
  8 +import java.io.InputStream;
  9 +
  10 +/**
  11 + * IO 工具类,用于 {@link cn.hutool.core.io.IoUtil} 缺失的方法
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +public class IoUtils {
  16 +
  17 + /**
  18 + * 从流中读取 UTF8 编码的内容
  19 + *
  20 + * @param in 输入流
  21 + * @param isClose 是否关闭
  22 + * @return 内容
  23 + * @throws IORuntimeException IO 异常
  24 + */
  25 + public static String readUtf8(InputStream in, boolean isClose) throws IORuntimeException {
  26 + return StrUtil.utf8Str(IoUtil.read(in, isClose));
  27 + }
  28 +
  29 +}
... ...