Commit 490f907ada7c51b325bf493013b789b4d4e964ba
1 parent
c4003396
完善 bpmnProcessDesigner 流程设计器的使用,基本可用了!
Showing
20 changed files
with
242 additions
and
135 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/form/BpmFormController.java
| 1 | package cn.iocoder.yudao.adminserver.modules.bpm.controller.form; | 1 | package cn.iocoder.yudao.adminserver.modules.bpm.controller.form; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.*; | ||
| 3 | import cn.iocoder.yudao.adminserver.modules.bpm.convert.form.BpmFormConvert; | 4 | import cn.iocoder.yudao.adminserver.modules.bpm.convert.form.BpmFormConvert; |
| 4 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO; | 5 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO; |
| 5 | import cn.iocoder.yudao.adminserver.modules.bpm.service.form.BpmFormService; | 6 | import cn.iocoder.yudao.adminserver.modules.bpm.service.form.BpmFormService; |
| 6 | -import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.*; | ||
| 7 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 9 | import io.swagger.annotations.Api; | 9 | import io.swagger.annotations.Api; |
| @@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.*; | @@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.*; | ||
| 15 | 15 | ||
| 16 | import javax.annotation.Resource; | 16 | import javax.annotation.Resource; |
| 17 | import javax.validation.Valid; | 17 | import javax.validation.Valid; |
| 18 | -import java.util.Collection; | ||
| 19 | import java.util.List; | 18 | import java.util.List; |
| 20 | 19 | ||
| 21 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 20 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| @@ -62,13 +61,11 @@ public class BpmFormController { | @@ -62,13 +61,11 @@ public class BpmFormController { | ||
| 62 | return success(BpmFormConvert.INSTANCE.convert(form)); | 61 | return success(BpmFormConvert.INSTANCE.convert(form)); |
| 63 | } | 62 | } |
| 64 | 63 | ||
| 65 | - @GetMapping("/list") | ||
| 66 | - @ApiOperation("获得动态表单列表") | ||
| 67 | - @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) | ||
| 68 | - @PreAuthorize("@ss.hasPermission('bpm:form:query')") | ||
| 69 | - public CommonResult<List<BpmFormRespVO>> getFormList(@RequestParam("ids") Collection<Long> ids) { | ||
| 70 | - List<BpmFormDO> list = formService.getFormList(ids); | ||
| 71 | - return success(BpmFormConvert.INSTANCE.convertList(list)); | 64 | + @GetMapping("/list-all-simple") |
| 65 | + @ApiOperation(value = "获得动态表单的精简列表", notes = "用于表单下拉框") | ||
| 66 | + public CommonResult<List<BpmFormSimpleRespVO>> getSimpleForms() { | ||
| 67 | + List<BpmFormDO> list = formService.getFormList(); | ||
| 68 | + return success(BpmFormConvert.INSTANCE.convertList2(list)); | ||
| 72 | } | 69 | } |
| 73 | 70 | ||
| 74 | @GetMapping("/page") | 71 | @GetMapping("/page") |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/form/vo/BpmFormSimpleRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@ApiModel("流程表单精简 Response VO") | ||
| 8 | +@Data | ||
| 9 | +public class BpmFormSimpleRespVO { | ||
| 10 | + | ||
| 11 | + @ApiModelProperty(value = "表单编号", required = true, example = "1024") | ||
| 12 | + private Long id; | ||
| 13 | + | ||
| 14 | + @ApiModelProperty(value = "表单名称", required = true, example = "芋道") | ||
| 15 | + private String name; | ||
| 16 | + | ||
| 17 | +} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/model/vo/BpmModelRespVO.java
| @@ -6,6 +6,8 @@ import lombok.Data; | @@ -6,6 +6,8 @@ import lombok.Data; | ||
| 6 | import lombok.EqualsAndHashCode; | 6 | import lombok.EqualsAndHashCode; |
| 7 | import lombok.ToString; | 7 | import lombok.ToString; |
| 8 | 8 | ||
| 9 | +import java.util.Date; | ||
| 10 | + | ||
| 9 | @ApiModel("流程模型的创建 Request VO") | 11 | @ApiModel("流程模型的创建 Request VO") |
| 10 | @Data | 12 | @Data |
| 11 | @EqualsAndHashCode(callSuper = true) | 13 | @EqualsAndHashCode(callSuper = true) |
| @@ -18,4 +20,7 @@ public class BpmModelRespVO extends BpmModelBaseVO { | @@ -18,4 +20,7 @@ public class BpmModelRespVO extends BpmModelBaseVO { | ||
| 18 | @ApiModelProperty(value = "BPMN XML", required = true) | 20 | @ApiModelProperty(value = "BPMN XML", required = true) |
| 19 | private String bpmnXml; | 21 | private String bpmnXml; |
| 20 | 22 | ||
| 23 | + @ApiModelProperty(value = "创建时间", required = true) | ||
| 24 | + private Date createTime; | ||
| 25 | + | ||
| 21 | } | 26 | } |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/form/BpmFormConvert.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.convert.form; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.convert.form; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.BpmFormCreateReqVO; | 3 | import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.BpmFormCreateReqVO; |
| 4 | import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.BpmFormRespVO; | 4 | import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.BpmFormRespVO; |
| 5 | +import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.BpmFormSimpleRespVO; | ||
| 5 | import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.BpmFormUpdateReqVO; | 6 | import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.BpmFormUpdateReqVO; |
| 6 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO; | 7 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO; |
| 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| @@ -26,7 +27,7 @@ public interface BpmFormConvert { | @@ -26,7 +27,7 @@ public interface BpmFormConvert { | ||
| 26 | 27 | ||
| 27 | BpmFormRespVO convert(BpmFormDO bean); | 28 | BpmFormRespVO convert(BpmFormDO bean); |
| 28 | 29 | ||
| 29 | - List<BpmFormRespVO> convertList(List<BpmFormDO> list); | 30 | + List<BpmFormSimpleRespVO> convertList2(List<BpmFormDO> list); |
| 30 | 31 | ||
| 31 | PageResult<BpmFormRespVO> convertPage(PageResult<BpmFormDO> page); | 32 | PageResult<BpmFormRespVO> convertPage(PageResult<BpmFormDO> page); |
| 32 | 33 |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/model/ModelConvert.java
| @@ -57,7 +57,20 @@ public interface ModelConvert { | @@ -57,7 +57,20 @@ public interface ModelConvert { | ||
| 57 | return modelRespVO; | 57 | return modelRespVO; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | - BpmModelRespVO convert(Model model); | 60 | + default BpmModelRespVO convert(Model model) { |
| 61 | + BpmModelRespVO modelRespVO = new BpmModelRespVO(); | ||
| 62 | + modelRespVO.setId(model.getId()); | ||
| 63 | + modelRespVO.setName(model.getName()); | ||
| 64 | + modelRespVO.setKey(model.getKey()); | ||
| 65 | + modelRespVO.setCategory(model.getCategory()); | ||
| 66 | + modelRespVO.setCreateTime(model.getCreateTime()); | ||
| 67 | + BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class); | ||
| 68 | + if (metaInfo != null) { | ||
| 69 | + modelRespVO.setFormId(metaInfo.getFormId()); | ||
| 70 | + modelRespVO.setDescription(metaInfo.getDescription()); | ||
| 71 | + } | ||
| 72 | + return modelRespVO; | ||
| 73 | + } | ||
| 61 | 74 | ||
| 62 | default BpmDefinitionCreateReqDTO convert2(Model model) { | 75 | default BpmDefinitionCreateReqDTO convert2(Model model) { |
| 63 | BpmDefinitionCreateReqDTO createReqDTO = new BpmDefinitionCreateReqDTO(); | 76 | BpmDefinitionCreateReqDTO createReqDTO = new BpmDefinitionCreateReqDTO(); |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java
| @@ -26,6 +26,8 @@ public interface BpmErrorCodeConstants { | @@ -26,6 +26,8 @@ public interface BpmErrorCodeConstants { | ||
| 26 | // ========== OA 工作流模块 1-009-002-000 ========== | 26 | // ========== OA 工作流模块 1-009-002-000 ========== |
| 27 | ErrorCode BPM_MODEL_KEY_EXISTS = new ErrorCode(1009002000, "已经存在流程标识为【{}】的流程"); | 27 | ErrorCode BPM_MODEL_KEY_EXISTS = new ErrorCode(1009002000, "已经存在流程标识为【{}】的流程"); |
| 28 | ErrorCode BPMN_MODEL_NOT_EXISTS = new ErrorCode(1009002001, "流程模型不存在"); | 28 | ErrorCode BPMN_MODEL_NOT_EXISTS = new ErrorCode(1009002001, "流程模型不存在"); |
| 29 | + ErrorCode BPMN_MODEL_KEY_VALID = new ErrorCode(1009002002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!"); | ||
| 30 | + | ||
| 29 | 31 | ||
| 30 | ErrorCode BPMN_MODEL_ERROR = new ErrorCode(1004001002, "工作流模型异常"); | 32 | ErrorCode BPMN_MODEL_ERROR = new ErrorCode(1004001002, "工作流模型异常"); |
| 31 | ErrorCode BPMN_MODEL_PROCESS_NOT_EXISTS = new ErrorCode(1004001009, "流程数据为空"); | 33 | ErrorCode BPMN_MODEL_PROCESS_NOT_EXISTS = new ErrorCode(1004001009, "流程数据为空"); |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/form/BpmFormService.java
| @@ -7,6 +7,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.BpmFormUpdate | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.form.vo.BpmFormUpdate | ||
| 7 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO; | 7 | import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO; |
| 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 9 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 9 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 10 | +import org.activiti.engine.repository.Model; | ||
| 10 | 11 | ||
| 11 | import javax.validation.Valid; | 12 | import javax.validation.Valid; |
| 12 | import java.util.Collection; | 13 | import java.util.Collection; |
| @@ -55,6 +56,13 @@ public interface BpmFormService { | @@ -55,6 +56,13 @@ public interface BpmFormService { | ||
| 55 | /** | 56 | /** |
| 56 | * 获得动态表单列表 | 57 | * 获得动态表单列表 |
| 57 | * | 58 | * |
| 59 | + * @return 动态表单列表 | ||
| 60 | + */ | ||
| 61 | + List<BpmFormDO> getFormList(); | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * 获得动态表单列表 | ||
| 65 | + * | ||
| 58 | * @param ids 编号 | 66 | * @param ids 编号 |
| 59 | * @return 动态表单列表 | 67 | * @return 动态表单列表 |
| 60 | */ | 68 | */ |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/form/impl/BpmFormServiceImpl.java
| @@ -76,6 +76,11 @@ public class BpmFormServiceImpl implements BpmFormService { | @@ -76,6 +76,11 @@ public class BpmFormServiceImpl implements BpmFormService { | ||
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | @Override | 78 | @Override |
| 79 | + public List<BpmFormDO> getFormList() { | ||
| 80 | + return formMapper.selectList(); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + @Override | ||
| 79 | public List<BpmFormDO> getFormList(Collection<Long> ids) { | 84 | public List<BpmFormDO> getFormList(Collection<Long> ids) { |
| 80 | return formMapper.selectBatchIds(ids); | 85 | return formMapper.selectBatchIds(ids); |
| 81 | } | 86 | } |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/model/impl/BpmModelServiceImpl.java
| @@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | @@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 13 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 13 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 14 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 14 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 15 | import cn.iocoder.yudao.framework.common.util.object.PageUtils; | 15 | import cn.iocoder.yudao.framework.common.util.object.PageUtils; |
| 16 | +import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; | ||
| 16 | import lombok.extern.slf4j.Slf4j; | 17 | import lombok.extern.slf4j.Slf4j; |
| 17 | import org.activiti.engine.RepositoryService; | 18 | import org.activiti.engine.RepositoryService; |
| 18 | import org.activiti.engine.repository.Model; | 19 | import org.activiti.engine.repository.Model; |
| @@ -29,8 +30,7 @@ import java.util.List; | @@ -29,8 +30,7 @@ import java.util.List; | ||
| 29 | import java.util.Map; | 30 | import java.util.Map; |
| 30 | import java.util.Set; | 31 | import java.util.Set; |
| 31 | 32 | ||
| 32 | -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.BPMN_MODEL_NOT_EXISTS; | ||
| 33 | -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.BPM_MODEL_KEY_EXISTS; | 33 | +import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; |
| 34 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 34 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 35 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | 35 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 36 | 36 | ||
| @@ -89,6 +89,9 @@ public class BpmModelServiceImpl implements BpmModelService { | @@ -89,6 +89,9 @@ public class BpmModelServiceImpl implements BpmModelService { | ||
| 89 | @Override | 89 | @Override |
| 90 | public BpmModelRespVO getModel(String id) { | 90 | public BpmModelRespVO getModel(String id) { |
| 91 | Model model = repositoryService.getModel(id); | 91 | Model model = repositoryService.getModel(id); |
| 92 | + if (model == null) { | ||
| 93 | + return null; | ||
| 94 | + } | ||
| 92 | BpmModelRespVO modelRespVO = ModelConvert.INSTANCE.convert(model); | 95 | BpmModelRespVO modelRespVO = ModelConvert.INSTANCE.convert(model); |
| 93 | // 拼接 bpmn XML | 96 | // 拼接 bpmn XML |
| 94 | byte[] bpmnBytes = repositoryService.getModelEditorSource(id); | 97 | byte[] bpmnBytes = repositoryService.getModelEditorSource(id); |
| @@ -99,12 +102,12 @@ public class BpmModelServiceImpl implements BpmModelService { | @@ -99,12 +102,12 @@ public class BpmModelServiceImpl implements BpmModelService { | ||
| 99 | @Override | 102 | @Override |
| 100 | @Transactional(rollbackFor = Exception.class) // 因为进行多个 activiti 操作,所以开启事务 | 103 | @Transactional(rollbackFor = Exception.class) // 因为进行多个 activiti 操作,所以开启事务 |
| 101 | public String createModel(BpmModelCreateReqVO createReqVO) { | 104 | public String createModel(BpmModelCreateReqVO createReqVO) { |
| 105 | + checkKeyNCName(createReqVO.getKey()); | ||
| 102 | // 校验流程标识已经存在 | 106 | // 校验流程标识已经存在 |
| 103 | Model keyModel = this.getModelByKey(createReqVO.getKey()); | 107 | Model keyModel = this.getModelByKey(createReqVO.getKey()); |
| 104 | if (keyModel != null) { | 108 | if (keyModel != null) { |
| 105 | - throw exception(BPM_MODEL_KEY_EXISTS); | 109 | + throw exception(BPM_MODEL_KEY_EXISTS, createReqVO.getKey()); |
| 106 | } | 110 | } |
| 107 | - // TODO @芋艿:需要校验下 key 的格式 | ||
| 108 | 111 | ||
| 109 | // 创建流程定义 | 112 | // 创建流程定义 |
| 110 | Model model = repositoryService.newModel(); | 113 | Model model = repositoryService.newModel(); |
| @@ -119,12 +122,12 @@ public class BpmModelServiceImpl implements BpmModelService { | @@ -119,12 +122,12 @@ public class BpmModelServiceImpl implements BpmModelService { | ||
| 119 | @Override | 122 | @Override |
| 120 | @Transactional(rollbackFor = Exception.class) // 因为进行多个 activiti 操作,所以开启事务 | 123 | @Transactional(rollbackFor = Exception.class) // 因为进行多个 activiti 操作,所以开启事务 |
| 121 | public void updateModel(BpmModelUpdateReqVO updateReqVO) { | 124 | public void updateModel(BpmModelUpdateReqVO updateReqVO) { |
| 125 | + checkKeyNCName(updateReqVO.getKey()); | ||
| 122 | // 校验流程模型存在 | 126 | // 校验流程模型存在 |
| 123 | Model model = repositoryService.getModel(updateReqVO.getId()); | 127 | Model model = repositoryService.getModel(updateReqVO.getId()); |
| 124 | if (model == null) { | 128 | if (model == null) { |
| 125 | throw exception(BPMN_MODEL_NOT_EXISTS); | 129 | throw exception(BPMN_MODEL_NOT_EXISTS); |
| 126 | } | 130 | } |
| 127 | - // TODO @芋艿:需要校验下 key 的格式 | ||
| 128 | 131 | ||
| 129 | // 修改流程定义 | 132 | // 修改流程定义 |
| 130 | ModelConvert.INSTANCE.copy(model, updateReqVO); | 133 | ModelConvert.INSTANCE.copy(model, updateReqVO); |
| @@ -173,4 +176,10 @@ public class BpmModelServiceImpl implements BpmModelService { | @@ -173,4 +176,10 @@ public class BpmModelServiceImpl implements BpmModelService { | ||
| 173 | return repositoryService.createModelQuery().modelKey(key).singleResult(); | 176 | return repositoryService.createModelQuery().modelKey(key).singleResult(); |
| 174 | } | 177 | } |
| 175 | 178 | ||
| 179 | + private void checkKeyNCName(String key) { | ||
| 180 | + if (!ValidationUtils.isXmlNCName(key)) { | ||
| 181 | + throw exception(BPMN_MODEL_KEY_VALID); | ||
| 182 | + } | ||
| 183 | + } | ||
| 184 | + | ||
| 176 | } | 185 | } |
yudao-admin-ui/src/api/bpm/form.js
| @@ -43,5 +43,10 @@ export function getFormPage(query) { | @@ -43,5 +43,10 @@ export function getFormPage(query) { | ||
| 43 | }) | 43 | }) |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | -export class exportFormExcel { | 46 | +// 获得动态表单的精简列表 |
| 47 | +export function getSimpleForms() { | ||
| 48 | + return request({ | ||
| 49 | + url: '/bpm/form/list-all-simple', | ||
| 50 | + method: 'get' | ||
| 51 | + }) | ||
| 47 | } | 52 | } |
yudao-admin-ui/src/components/RADME.md
| @@ -5,4 +5,17 @@ github 地址:https://github.com/JakHuang/form-generator | @@ -5,4 +5,17 @@ github 地址:https://github.com/JakHuang/form-generator | ||
| 5 | * generator | 5 | * generator |
| 6 | * parser | 6 | * parser |
| 7 | * render | 7 | * render |
| 8 | -* tinymce | ||
| 9 | \ No newline at end of file | 8 | \ No newline at end of file |
| 9 | +* tinymce | ||
| 10 | + | ||
| 11 | +## bpmn-process-designer | ||
| 12 | + | ||
| 13 | +github 地址:https://github.com/miyuesc/bpmn-process-designer | ||
| 14 | + | ||
| 15 | +* bpmnProcessDesigner | ||
| 16 | + | ||
| 17 | +TODO 目前存在的问题,如果选择 activiti 类型时,因为不支持内置表单的设计,所以会报 Error: unknown type activiti:FormData 错误。具体可见 https://github.com/miyuesc/bpmn-process-designer/issues/16 。 | ||
| 18 | + | ||
| 19 | +另外几个流程设计器的选型: | ||
| 20 | + | ||
| 21 | +* https://gitee.com/jimlow/vue-bpmn 相比差一些,已经停止维护,不算推荐。 | ||
| 22 | +* https://github.com/GoldSubmarine/workflow-bpmn-modeler 仅支持 flowable 流程引擎。如果只考虑 flowable 的话,也是非常不错的选择。 | ||
| 10 | \ No newline at end of file | 23 | \ No newline at end of file |
yudao-admin-ui/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue
| @@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
| 4 | <slot name="control-header"></slot> | 4 | <slot name="control-header"></slot> |
| 5 | <template v-if="!$slots['control-header']"> | 5 | <template v-if="!$slots['control-header']"> |
| 6 | <el-button-group key="file-control"> | 6 | <el-button-group key="file-control"> |
| 7 | - <el-button :size="headerButtonSize" :type="headerButtonType" icon="el-icon-folder-opened" @click="$refs.refFile.click()">打开文件</el-button> | 7 | + <el-button :size="headerButtonSize" icon="el-icon-folder-opened" @click="$refs.refFile.click()">打开文件</el-button> |
| 8 | <el-tooltip effect="light"> | 8 | <el-tooltip effect="light"> |
| 9 | <div slot="content"> | 9 | <div slot="content"> |
| 10 | <el-button :size="headerButtonSize" type="text" @click="downloadProcessAsXml()">下载为XML文件</el-button> | 10 | <el-button :size="headerButtonSize" type="text" @click="downloadProcessAsXml()">下载为XML文件</el-button> |
| @@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
| 13 | <br /> | 13 | <br /> |
| 14 | <el-button :size="headerButtonSize" type="text" @click="downloadProcessAsBpmn()">下载为BPMN文件</el-button> | 14 | <el-button :size="headerButtonSize" type="text" @click="downloadProcessAsBpmn()">下载为BPMN文件</el-button> |
| 15 | </div> | 15 | </div> |
| 16 | - <el-button :size="headerButtonSize" :type="headerButtonType" icon="el-icon-download">下载文件</el-button> | 16 | + <el-button :size="headerButtonSize" icon="el-icon-download">下载文件</el-button> |
| 17 | </el-tooltip> | 17 | </el-tooltip> |
| 18 | <el-tooltip effect="light"> | 18 | <el-tooltip effect="light"> |
| 19 | <div slot="content"> | 19 | <div slot="content"> |
| @@ -21,10 +21,10 @@ | @@ -21,10 +21,10 @@ | ||
| 21 | <br /> | 21 | <br /> |
| 22 | <el-button :size="headerButtonSize" type="text" @click="previewProcessJson">预览JSON</el-button> | 22 | <el-button :size="headerButtonSize" type="text" @click="previewProcessJson">预览JSON</el-button> |
| 23 | </div> | 23 | </div> |
| 24 | - <el-button :size="headerButtonSize" :type="headerButtonType" icon="el-icon-view">预览</el-button> | 24 | + <el-button :size="headerButtonSize" icon="el-icon-view">预览</el-button> |
| 25 | </el-tooltip> | 25 | </el-tooltip> |
| 26 | <el-tooltip v-if="simulation" effect="light" :content="this.simulationStatus ? '退出模拟' : '开启模拟'"> | 26 | <el-tooltip v-if="simulation" effect="light" :content="this.simulationStatus ? '退出模拟' : '开启模拟'"> |
| 27 | - <el-button :size="headerButtonSize" :type="headerButtonType" icon="el-icon-cpu" @click="processSimulation"> | 27 | + <el-button :size="headerButtonSize" icon="el-icon-cpu" @click="processSimulation"> |
| 28 | 模拟 | 28 | 模拟 |
| 29 | </el-button> | 29 | </el-button> |
| 30 | </el-tooltip> | 30 | </el-tooltip> |
| @@ -72,6 +72,7 @@ | @@ -72,6 +72,7 @@ | ||
| 72 | <el-button :size="headerButtonSize" icon="el-icon-refresh" @click="processRestart" /> | 72 | <el-button :size="headerButtonSize" icon="el-icon-refresh" @click="processRestart" /> |
| 73 | </el-tooltip> | 73 | </el-tooltip> |
| 74 | </el-button-group> | 74 | </el-button-group> |
| 75 | + <el-button :size="headerButtonSize" :type="headerButtonType" icon="el-icon-plus" @click="processSave">保存模型</el-button> | ||
| 75 | </template> | 76 | </template> |
| 76 | <!-- 用于打开本地文件--> | 77 | <!-- 用于打开本地文件--> |
| 77 | <input type="file" id="files" ref="refFile" style="display: none" accept=".xml, .bpmn" @change="importLocalFile" /> | 78 | <input type="file" id="files" ref="refFile" style="display: none" accept=".xml, .bpmn" @change="importLocalFile" /> |
| @@ -111,8 +112,9 @@ export default { | @@ -111,8 +112,9 @@ export default { | ||
| 111 | componentName: "MyProcessDesigner", | 112 | componentName: "MyProcessDesigner", |
| 112 | props: { | 113 | props: { |
| 113 | value: String, // xml 字符串 | 114 | value: String, // xml 字符串 |
| 114 | - processId: String, | ||
| 115 | - processName: String, | 115 | + processId: String, // 流程 key 标识 |
| 116 | + processName: String, // 流程 name 名字 | ||
| 117 | + formId: Number, // 流程 form 表单编号 | ||
| 116 | translations: Object, // 自定义的翻译文件 | 118 | translations: Object, // 自定义的翻译文件 |
| 117 | additionalModel: [Object, Array], // 自定义model | 119 | additionalModel: [Object, Array], // 自定义model |
| 118 | moddleExtension: Object, // 自定义moddle | 120 | moddleExtension: Object, // 自定义moddle |
| @@ -244,6 +246,11 @@ export default { | @@ -244,6 +246,11 @@ export default { | ||
| 244 | this.bpmnModeler = null; | 246 | this.bpmnModeler = null; |
| 245 | }); | 247 | }); |
| 246 | }, | 248 | }, |
| 249 | + watch: { | ||
| 250 | + value: function (newValue) { // 在 xmlString 发生变化时,重新创建,从而绘制流程图 | ||
| 251 | + this.createNewDiagram(newValue); | ||
| 252 | + } | ||
| 253 | + }, | ||
| 247 | methods: { | 254 | methods: { |
| 248 | initBpmnModeler() { | 255 | initBpmnModeler() { |
| 249 | if (this.bpmnModeler) return; | 256 | if (this.bpmnModeler) return; |
| @@ -445,6 +452,17 @@ export default { | @@ -445,6 +452,17 @@ export default { | ||
| 445 | this.previewType = "json"; | 452 | this.previewType = "json"; |
| 446 | this.previewModelVisible = true; | 453 | this.previewModelVisible = true; |
| 447 | }); | 454 | }); |
| 455 | + }, | ||
| 456 | + /* ------------------------------------------------ 芋道源码 methods ------------------------------------------------------ */ | ||
| 457 | + async processSave() { | ||
| 458 | + const { err, xml } = await this.bpmnModeler.saveXML(); | ||
| 459 | + // 读取异常时抛出异常 | ||
| 460 | + if (err) { | ||
| 461 | + this.msgError('保存模型失败,请重试!') | ||
| 462 | + return | ||
| 463 | + } | ||
| 464 | + // 触发 save 事件 | ||
| 465 | + this.$emit('save', xml) | ||
| 448 | } | 466 | } |
| 449 | } | 467 | } |
| 450 | }; | 468 | }; |
yudao-admin-ui/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue
| @@ -3,7 +3,8 @@ | @@ -3,7 +3,8 @@ | ||
| 3 | <el-collapse v-model="activeTab"> | 3 | <el-collapse v-model="activeTab"> |
| 4 | <el-collapse-item name="base"> | 4 | <el-collapse-item name="base"> |
| 5 | <div slot="title" class="panel-tab__title"><i class="el-icon-info"></i>常规</div> | 5 | <div slot="title" class="panel-tab__title"><i class="el-icon-info"></i>常规</div> |
| 6 | - <element-base-info :id-edit-disabled="idEditDisabled" :business-object="elementBusinessObject" :type="elementType" /> | 6 | + <element-base-info :id-edit-disabled="idEditDisabled" :business-object="elementBusinessObject" :type="elementType" |
| 7 | + :model="model" /> | ||
| 7 | </el-collapse-item> | 8 | </el-collapse-item> |
| 8 | <el-collapse-item name="condition" v-if="elementType === 'Process'" key="message"> | 9 | <el-collapse-item name="condition" v-if="elementType === 'Process'" key="message"> |
| 9 | <div slot="title" class="panel-tab__title"><i class="el-icon-s-comment"></i>消息与信号</div> | 10 | <div slot="title" class="panel-tab__title"><i class="el-icon-s-comment"></i>消息与信号</div> |
| @@ -89,7 +90,8 @@ export default { | @@ -89,7 +90,8 @@ export default { | ||
| 89 | idEditDisabled: { | 90 | idEditDisabled: { |
| 90 | type: Boolean, | 91 | type: Boolean, |
| 91 | default: false | 92 | default: false |
| 92 | - } | 93 | + }, |
| 94 | + model: Object, // 流程模型的数据 | ||
| 93 | }, | 95 | }, |
| 94 | provide() { | 96 | provide() { |
| 95 | return { | 97 | return { |
| @@ -159,6 +161,7 @@ export default { | @@ -159,6 +161,7 @@ export default { | ||
| 159 | // 初始化数据 | 161 | // 初始化数据 |
| 160 | initFormOnChanged(element) { | 162 | initFormOnChanged(element) { |
| 161 | let activatedElement = element; | 163 | let activatedElement = element; |
| 164 | + // debugger | ||
| 162 | if (!activatedElement) { | 165 | if (!activatedElement) { |
| 163 | activatedElement = | 166 | activatedElement = |
| 164 | window.bpmnInstances.elementRegistry.find(el => el.type === "bpmn:Process") ?? | 167 | window.bpmnInstances.elementRegistry.find(el => el.type === "bpmn:Process") ?? |
yudao-admin-ui/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue
| 1 | <template> | 1 | <template> |
| 2 | <div class="panel-tab__content"> | 2 | <div class="panel-tab__content"> |
| 3 | - <el-form size="mini" label-width="90px" @submit.native.prevent> | ||
| 4 | - <el-form-item label="ID"> | ||
| 5 | - <el-input | ||
| 6 | - v-model="elementBaseInfo.id" | ||
| 7 | - :disabled="idEditDisabled || elementBaseInfo.$type === 'bpmn:Process'" | ||
| 8 | - clearable | ||
| 9 | - @change="updateBaseInfo('id')" | ||
| 10 | - /> | 3 | + <el-form size="mini" label-width="90px" :model="model" :rules="rules" @submit.native.prevent> |
| 4 | + <el-form-item label="流程标识" prop="key"> | ||
| 5 | + <el-input v-model="model.key" placeholder="请输入流标标识" | ||
| 6 | + :disabled="model.id !== undefined && model.id.length > 0"/> | ||
| 11 | </el-form-item> | 7 | </el-form-item> |
| 12 | - <el-form-item label="名称"> | ||
| 13 | - <el-input v-model="elementBaseInfo.name" clearable @change="updateBaseInfo('name')" /> | 8 | + <el-form-item label="流程名称" prop="name"> |
| 9 | + <el-input v-model="model.name" placeholder="请输入流程名称" clearable /> | ||
| 10 | + </el-form-item> | ||
| 11 | + <el-form-item label="流程分类" prop="category"> | ||
| 12 | + <el-select v-model="model.category" placeholder="请选择流程分类" clearable style="width: 100%"> | ||
| 13 | + <el-option v-for="dict in categoryDictDatas" :key="dict.value" :label="dict.label" :value="dict.value"/> | ||
| 14 | + </el-select> | ||
| 15 | + </el-form-item> | ||
| 16 | + <el-form-item label="流程表单" prop="formId"> | ||
| 17 | + <el-select v-model="model.formId" placeholder="请选择流程表单,非必选哟!" clearable style="width: 100%"> | ||
| 18 | + <el-option v-for="form in forms" :key="form.id" :label="form.name" :value="form.id"/> | ||
| 19 | + </el-select> | ||
| 20 | + </el-form-item> | ||
| 21 | + <el-form-item label="流程描述" prop="description"> | ||
| 22 | + <el-input type="textarea" v-model="model.description" clearable /> | ||
| 14 | </el-form-item> | 23 | </el-form-item> |
| 15 | - <!--流程的基础属性--> | ||
| 16 | - <template v-if="elementBaseInfo.$type === 'bpmn:Process'"> | ||
| 17 | - <el-form-item label="版本标签"> | ||
| 18 | - <el-input v-model="elementBaseInfo.versionTag" clearable @change="updateBaseInfo('versionTag')" /> | ||
| 19 | - </el-form-item> | ||
| 20 | - <el-form-item label="可执行"> | ||
| 21 | - <el-switch v-model="elementBaseInfo.isExecutable" active-text="是" inactive-text="否" @change="updateBaseInfo('isExecutable')" /> | ||
| 22 | - </el-form-item> | ||
| 23 | - </template> | ||
| 24 | </el-form> | 24 | </el-form> |
| 25 | </div> | 25 | </div> |
| 26 | </template> | 26 | </template> |
| 27 | <script> | 27 | <script> |
| 28 | +import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | ||
| 29 | +import {getSimpleForms} from "@/api/bpm/form"; | ||
| 30 | +import {getModel} from "@/api/bpm/model"; | ||
| 31 | + | ||
| 28 | export default { | 32 | export default { |
| 29 | name: "ElementBaseInfo", | 33 | name: "ElementBaseInfo", |
| 30 | props: { | 34 | props: { |
| 31 | businessObject: Object, | 35 | businessObject: Object, |
| 32 | - type: String, | ||
| 33 | - idEditDisabled: { | ||
| 34 | - type: Boolean, | ||
| 35 | - default: true | ||
| 36 | - } | 36 | + model: Object, // 流程模型的数据 |
| 37 | }, | 37 | }, |
| 38 | data() { | 38 | data() { |
| 39 | return { | 39 | return { |
| 40 | - elementBaseInfo: {} | 40 | + elementBaseInfo: {}, |
| 41 | + // 流程表单的下拉框的数据 | ||
| 42 | + forms: [], | ||
| 43 | + // 流程模型的校验 | ||
| 44 | + rules: { | ||
| 45 | + key: [{ required: true, message: "流程标识不能为空", trigger: "blur" }], | ||
| 46 | + name: [{ required: true, message: "流程名称不能为空", trigger: "blur" }], | ||
| 47 | + category: [{ required: true, message: "流程分类不能为空", trigger: "blur" }], | ||
| 48 | + }, | ||
| 49 | + // 数据字典 | ||
| 50 | + categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY), | ||
| 41 | }; | 51 | }; |
| 42 | }, | 52 | }, |
| 43 | watch: { | 53 | watch: { |
| @@ -50,12 +60,19 @@ export default { | @@ -50,12 +60,19 @@ export default { | ||
| 50 | } | 60 | } |
| 51 | } | 61 | } |
| 52 | }, | 62 | }, |
| 63 | + created() { | ||
| 64 | + // 获得流程表单的下拉框的数据 | ||
| 65 | + getSimpleForms().then(response => { | ||
| 66 | + this.forms = response.data | ||
| 67 | + }) | ||
| 68 | + }, | ||
| 53 | methods: { | 69 | methods: { |
| 54 | resetBaseInfo() { | 70 | resetBaseInfo() { |
| 55 | this.bpmnElement = window?.bpmnInstances?.bpmnElement; | 71 | this.bpmnElement = window?.bpmnInstances?.bpmnElement; |
| 56 | this.elementBaseInfo = JSON.parse(JSON.stringify(this.bpmnElement.businessObject)); | 72 | this.elementBaseInfo = JSON.parse(JSON.stringify(this.bpmnElement.businessObject)); |
| 57 | }, | 73 | }, |
| 58 | updateBaseInfo(key) { | 74 | updateBaseInfo(key) { |
| 75 | + // 触发 elementBaseInfo 对应的字段 | ||
| 59 | const attrObj = Object.create(null); | 76 | const attrObj = Object.create(null); |
| 60 | attrObj[key] = this.elementBaseInfo[key]; | 77 | attrObj[key] = this.elementBaseInfo[key]; |
| 61 | if (key === "id") { | 78 | if (key === "id") { |
yudao-admin-ui/src/main.js
| @@ -76,11 +76,10 @@ Vue.component('RightToolbar', RightToolbar) | @@ -76,11 +76,10 @@ Vue.component('RightToolbar', RightToolbar) | ||
| 76 | Vue.use(permission) | 76 | Vue.use(permission) |
| 77 | // Vue.use(hljs.vuePlugin); | 77 | // Vue.use(hljs.vuePlugin); |
| 78 | 78 | ||
| 79 | -// TODO 芋艿:bpmnProcessDesigner 引入 | 79 | +// bpmnProcessDesigner 需要引入 |
| 80 | import MyPD from "@/components/bpmnProcessDesigner/package/index.js"; | 80 | import MyPD from "@/components/bpmnProcessDesigner/package/index.js"; |
| 81 | Vue.use(MyPD); | 81 | Vue.use(MyPD); |
| 82 | import "@/components/bpmnProcessDesigner/package/theme/index.scss"; | 82 | import "@/components/bpmnProcessDesigner/package/theme/index.scss"; |
| 83 | -// TODO 芋艿:bpmnProcessDesigner 引入 | ||
| 84 | import "bpmn-js/dist/assets/diagram-js.css"; | 83 | import "bpmn-js/dist/assets/diagram-js.css"; |
| 85 | import "bpmn-js/dist/assets/bpmn-font/css/bpmn.css"; | 84 | import "bpmn-js/dist/assets/bpmn-font/css/bpmn.css"; |
| 86 | import "bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css"; | 85 | import "bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css"; |
yudao-admin-ui/src/views/bpm/model/index.vue
| @@ -67,12 +67,6 @@ | @@ -67,12 +67,6 @@ | ||
| 67 | <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 67 | <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 68 | @pagination="getList"/> | 68 | @pagination="getList"/> |
| 69 | 69 | ||
| 70 | - <!-- 流程编辑器 --> | ||
| 71 | -<!-- <el-dialog class="bpmnclass dialogClass" :visible.sync="showBpmnOpen" :before-cancel="cancel" :fullscreen="true">--> | ||
| 72 | -<!-- <vue-bpmn v-if="showBpmnOpen" product="activiti" @processSave="processSave"--> | ||
| 73 | -<!-- :bpmnXml="bpmnXML" :bpmnData="bpmnData" @beforeClose="cancel" />--> | ||
| 74 | -<!-- </el-dialog>--> | ||
| 75 | - | ||
| 76 | <!-- 流程表单配置详情 --> | 70 | <!-- 流程表单配置详情 --> |
| 77 | <el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body> | 71 | <el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body> |
| 78 | <div class="test-form"> | 72 | <div class="test-form"> |
| @@ -83,8 +77,7 @@ | @@ -83,8 +77,7 @@ | ||
| 83 | </template> | 77 | </template> |
| 84 | 78 | ||
| 85 | <script> | 79 | <script> |
| 86 | -import {deleteModel, deployModel, createModel, updateModel, getModelPage, getModel} from "@/api/bpm/model"; | ||
| 87 | -// import VueBpmn from "@/components/bpmn/VueBpmn"; | 80 | +import {deleteModel, deployModel, getModelPage} from "@/api/bpm/model"; |
| 88 | import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | 81 | import {DICT_TYPE, getDictDatas} from "@/utils/dict"; |
| 89 | import {getForm} from "@/api/bpm/form"; | 82 | import {getForm} from "@/api/bpm/form"; |
| 90 | import {decodeFields} from "@/utils/formGenerator"; | 83 | import {decodeFields} from "@/utils/formGenerator"; |
| @@ -93,8 +86,7 @@ import Parser from '@/components/parser/Parser' | @@ -93,8 +86,7 @@ import Parser from '@/components/parser/Parser' | ||
| 93 | export default { | 86 | export default { |
| 94 | name: "model", | 87 | name: "model", |
| 95 | components: { | 88 | components: { |
| 96 | - Parser, | ||
| 97 | - // VueBpmn | 89 | + Parser |
| 98 | }, | 90 | }, |
| 99 | data() { | 91 | data() { |
| 100 | return { | 92 | return { |
| @@ -157,55 +149,22 @@ export default { | @@ -157,55 +149,22 @@ export default { | ||
| 157 | this.resetForm("queryForm"); | 149 | this.resetForm("queryForm"); |
| 158 | this.handleQuery(); | 150 | this.handleQuery(); |
| 159 | }, | 151 | }, |
| 160 | - processSave(data) { | ||
| 161 | - // TODO 芋艿:临时写死的参数 | ||
| 162 | - data.category = '1' | ||
| 163 | - data.formId = 11 | ||
| 164 | - | ||
| 165 | - // 修改的提交 | ||
| 166 | - if (data.id) { | ||
| 167 | - updateModel(data).then(response => { | ||
| 168 | - this.msgSuccess("修改成功"); | ||
| 169 | - // 关闭弹窗,刷新列表 | ||
| 170 | - this.showBpmnOpen = false | ||
| 171 | - this.getList(); | ||
| 172 | - }) | ||
| 173 | - return | ||
| 174 | - } | ||
| 175 | - // 添加的提交 | ||
| 176 | - createModel(data).then(response => { | ||
| 177 | - this.bpmnData.id = response.data | ||
| 178 | - this.msgSuccess("保存成功"); | ||
| 179 | - // 关闭弹窗,刷新列表 | ||
| 180 | - this.showBpmnOpen = false | ||
| 181 | - this.getList(); | ||
| 182 | - }) | ||
| 183 | - }, | 152 | + /** 新增按钮操作 */ |
| 184 | handleAdd() { | 153 | handleAdd() { |
| 185 | - // 重置 Model 信息 | ||
| 186 | - this.reset() | ||
| 187 | - // 打开弹窗 | ||
| 188 | - this.showBpmnOpen = true | ||
| 189 | - }, | ||
| 190 | - cancel() { | ||
| 191 | - // 打开弹窗 | ||
| 192 | - this.showBpmnOpen = false | ||
| 193 | - // 重置 Model 信息 | ||
| 194 | - this.reset() | ||
| 195 | - // 刷新列表 | ||
| 196 | - this.getList() | 154 | + this.$router.push({ |
| 155 | + path:"/bpm/manager/model/edit" | ||
| 156 | + }); | ||
| 197 | }, | 157 | }, |
| 158 | + /** 修改按钮操作 */ | ||
| 198 | handleUpdate(row) { | 159 | handleUpdate(row) { |
| 199 | - // 重置 Model 信息 | ||
| 200 | - this.reset() | ||
| 201 | - // 获得 Model 信息 | ||
| 202 | - getModel(row.id).then(response => { | ||
| 203 | - this.bpmnXML = response.data.bpmnXml | ||
| 204 | - this.bpmnData = response.data | ||
| 205 | - // 打开弹窗 | ||
| 206 | - this.showBpmnOpen = true | ||
| 207 | - }) | 160 | + this.$router.push({ |
| 161 | + path:"/bpm/manager/model/edit", | ||
| 162 | + query:{ | ||
| 163 | + modelId: row.id | ||
| 164 | + } | ||
| 165 | + }); | ||
| 208 | }, | 166 | }, |
| 167 | + /** 删除按钮操作 */ | ||
| 209 | handleDelete(row) { | 168 | handleDelete(row) { |
| 210 | const that = this; | 169 | const that = this; |
| 211 | this.$confirm('是否删除该流程!!', "警告", { | 170 | this.$confirm('是否删除该流程!!', "警告", { |
| @@ -219,6 +178,7 @@ export default { | @@ -219,6 +178,7 @@ export default { | ||
| 219 | }) | 178 | }) |
| 220 | }) | 179 | }) |
| 221 | }, | 180 | }, |
| 181 | + /** 部署按钮操作 */ | ||
| 222 | handleDeploy(row) { | 182 | handleDeploy(row) { |
| 223 | const that = this; | 183 | const that = this; |
| 224 | this.$confirm('是否部署该流程!!', "提示", { | 184 | this.$confirm('是否部署该流程!!', "提示", { |
| @@ -248,19 +208,3 @@ export default { | @@ -248,19 +208,3 @@ export default { | ||
| 248 | } | 208 | } |
| 249 | }; | 209 | }; |
| 250 | </script> | 210 | </script> |
| 251 | -<style> | ||
| 252 | -.el-dialog > .el-dialog__body{ | ||
| 253 | - margin: 0; | ||
| 254 | - border: 0; | ||
| 255 | -} | ||
| 256 | -.bpmn-viewer-header{ | ||
| 257 | - background: white; | ||
| 258 | -} | ||
| 259 | -.v-modal{ | ||
| 260 | - z-index: 2000!important; | ||
| 261 | -} | ||
| 262 | -.dialogClass{ | ||
| 263 | - padding: 0 ; | ||
| 264 | -} | ||
| 265 | -</style> | ||
| 266 | - |
yudao-admin-ui/src/views/bpm/model/modelEditor.vue
| 1 | <template> | 1 | <template> |
| 2 | <div class="app-container"> | 2 | <div class="app-container"> |
| 3 | 3 | ||
| 4 | - <!-- 流程编辑器 --> | 4 | + <!-- 流程设计器,负责绘制流程等 --> |
| 5 | <my-process-designer :key="`designer-${reloadIndex}`" v-model="xmlString" v-bind="controlForm" | 5 | <my-process-designer :key="`designer-${reloadIndex}`" v-model="xmlString" v-bind="controlForm" |
| 6 | - keyboard ref="processDesigner" @init-finished="initModeler"/> | ||
| 7 | - <!-- 右边工具栏 --> | ||
| 8 | - <my-properties-panel :key="`penal-${reloadIndex}`" :bpmn-modeler="modeler" :prefix="controlForm.prefix" class="process-panel" /> | 6 | + keyboard ref="processDesigner" @init-finished="initModeler" |
| 7 | + @save="save"/> | ||
| 8 | + | ||
| 9 | + <!-- 流程属性器,负责编辑每个流程节点的属性 --> | ||
| 10 | + <my-properties-panel :key="`penal-${reloadIndex}`" :bpmn-modeler="modeler" :prefix="controlForm.prefix" class="process-panel" | ||
| 11 | + :model="model" /> | ||
| 9 | 12 | ||
| 10 | </div> | 13 | </div> |
| 11 | </template> | 14 | </template> |
| @@ -18,6 +21,7 @@ import CustomContentPadProvider from "@/components/bpmnProcessDesigner/package/d | @@ -18,6 +21,7 @@ import CustomContentPadProvider from "@/components/bpmnProcessDesigner/package/d | ||
| 18 | import CustomPaletteProvider from "@/components/bpmnProcessDesigner/package/designer/plugins/palette"; | 21 | import CustomPaletteProvider from "@/components/bpmnProcessDesigner/package/designer/plugins/palette"; |
| 19 | // import xmlObj2json from "./utils/xml2json"; | 22 | // import xmlObj2json from "./utils/xml2json"; |
| 20 | import MyProcessPalette from "@/components/bpmnProcessDesigner/package/palette/ProcessPalette"; | 23 | import MyProcessPalette from "@/components/bpmnProcessDesigner/package/palette/ProcessPalette"; |
| 24 | +import {createModel, getModel, updateModel} from "@/api/bpm/model"; | ||
| 21 | // 自定义侧边栏 | 25 | // 自定义侧边栏 |
| 22 | // import MyProcessPanel from "../package/process-panel/ProcessPanel"; | 26 | // import MyProcessPanel from "../package/process-panel/ProcessPanel"; |
| 23 | 27 | ||
| @@ -32,23 +36,34 @@ export default { | @@ -32,23 +36,34 @@ export default { | ||
| 32 | controlDrawerVisible: false, | 36 | controlDrawerVisible: false, |
| 33 | translationsSelf: translations, | 37 | translationsSelf: translations, |
| 34 | controlForm: { | 38 | controlForm: { |
| 35 | - processId: "", | ||
| 36 | - processName: "", | ||
| 37 | simulation: true, | 39 | simulation: true, |
| 38 | labelEditing: false, | 40 | labelEditing: false, |
| 39 | labelVisible: false, | 41 | labelVisible: false, |
| 40 | prefix: "activiti", | 42 | prefix: "activiti", |
| 41 | headerButtonSize: "mini", | 43 | headerButtonSize: "mini", |
| 42 | - // additionalModel: [] | ||
| 43 | additionalModel: [CustomContentPadProvider, CustomPaletteProvider] | 44 | additionalModel: [CustomContentPadProvider, CustomPaletteProvider] |
| 44 | }, | 45 | }, |
| 45 | addis: { | 46 | addis: { |
| 46 | CustomContentPadProvider, | 47 | CustomContentPadProvider, |
| 47 | CustomPaletteProvider | 48 | CustomPaletteProvider |
| 48 | - } | 49 | + }, |
| 50 | + // 流程模型的信息 | ||
| 51 | + model: {}, | ||
| 49 | }; | 52 | }; |
| 50 | }, | 53 | }, |
| 51 | - created() {}, | 54 | + created() { |
| 55 | + // 如果 modelId 非空,说明是修改流程模型 | ||
| 56 | + const modelId = this.$route.query && this.$route.query.modelId | ||
| 57 | + if (modelId) { | ||
| 58 | + getModel(modelId).then(response => { | ||
| 59 | + this.xmlString = response.data.bpmnXml | ||
| 60 | + this.model = { | ||
| 61 | + ...response.data, | ||
| 62 | + bpmnXml: undefined, // 清空 bpmnXml 属性 | ||
| 63 | + } | ||
| 64 | + }) | ||
| 65 | + } | ||
| 66 | + }, | ||
| 52 | methods: { | 67 | methods: { |
| 53 | initModeler(modeler) { | 68 | initModeler(modeler) { |
| 54 | setTimeout(() => { | 69 | setTimeout(() => { |
| @@ -70,7 +85,34 @@ export default { | @@ -70,7 +85,34 @@ export default { | ||
| 70 | // this.xmlString = undefined; | 85 | // this.xmlString = undefined; |
| 71 | // this.$refs.processDesigner.processRestart(); | 86 | // this.$refs.processDesigner.processRestart(); |
| 72 | // } | 87 | // } |
| 73 | - } | 88 | + }, |
| 89 | + save(bpmnXml) { | ||
| 90 | + const data = { | ||
| 91 | + ...this.model, | ||
| 92 | + bpmnXml: bpmnXml, // this.bpmnXml 只是初始化流程图,后续修改无法通过它获得 | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + // 修改的提交 | ||
| 96 | + if (data.id) { | ||
| 97 | + updateModel(data).then(response => { | ||
| 98 | + this.msgSuccess("修改成功") | ||
| 99 | + // 跳转回去 | ||
| 100 | + this.close() | ||
| 101 | + }) | ||
| 102 | + return | ||
| 103 | + } | ||
| 104 | + // 添加的提交 | ||
| 105 | + createModel(data).then(response => { | ||
| 106 | + this.msgSuccess("保存成功") | ||
| 107 | + // 跳转回去 | ||
| 108 | + this.close() | ||
| 109 | + }) | ||
| 110 | + }, | ||
| 111 | + /** 关闭按钮 */ | ||
| 112 | + close() { | ||
| 113 | + this.$store.dispatch("tagsView/delView", this.$route); | ||
| 114 | + this.$router.push({ path: "/bpm/manager/model", query: { t: Date.now()}}) | ||
| 115 | + }, | ||
| 74 | } | 116 | } |
| 75 | }; | 117 | }; |
| 76 | </script> | 118 | </script> |
yudao-admin-ui/vue.config.js
| @@ -35,6 +35,7 @@ module.exports = { | @@ -35,6 +35,7 @@ module.exports = { | ||
| 35 | // detail: https://cli.vuejs.org/config/#devserver-proxy | 35 | // detail: https://cli.vuejs.org/config/#devserver-proxy |
| 36 | [process.env.VUE_APP_BASE_API]: { | 36 | [process.env.VUE_APP_BASE_API]: { |
| 37 | target: `http://localhost:48080`, | 37 | target: `http://localhost:48080`, |
| 38 | + // target: `http://api-dashboard.yudao.iocoder.cn`, | ||
| 38 | changeOrigin: true, | 39 | changeOrigin: true, |
| 39 | pathRewrite: { | 40 | pathRewrite: { |
| 40 | ['^' + process.env.VUE_APP_BASE_API]: '' | 41 | ['^' + process.env.VUE_APP_BASE_API]: '' |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/validation/ValidationUtils.java
| @@ -12,7 +12,9 @@ import java.util.regex.Pattern; | @@ -12,7 +12,9 @@ import java.util.regex.Pattern; | ||
| 12 | */ | 12 | */ |
| 13 | public class ValidationUtils { | 13 | public class ValidationUtils { |
| 14 | 14 | ||
| 15 | - private static Pattern PATTERN_URL = Pattern.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"); | 15 | + private static final Pattern PATTERN_URL = Pattern.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"); |
| 16 | + | ||
| 17 | + private static final Pattern PATTERN_XML_NCNAME = Pattern.compile("[a-zA-Z_][\\-_.0-9_a-zA-Z$]*"); | ||
| 16 | 18 | ||
| 17 | public static boolean isMobile(String mobile) { | 19 | public static boolean isMobile(String mobile) { |
| 18 | if (StrUtil.length(mobile) != 11) { | 20 | if (StrUtil.length(mobile) != 11) { |
| @@ -27,4 +29,9 @@ public class ValidationUtils { | @@ -27,4 +29,9 @@ public class ValidationUtils { | ||
| 27 | && PATTERN_URL.matcher(url).matches(); | 29 | && PATTERN_URL.matcher(url).matches(); |
| 28 | } | 30 | } |
| 29 | 31 | ||
| 32 | + public static boolean isXmlNCName(String str) { | ||
| 33 | + return StringUtils.hasText(str) | ||
| 34 | + && PATTERN_XML_NCNAME.matcher(str).matches(); | ||
| 35 | + } | ||
| 36 | + | ||
| 30 | } | 37 | } |
更新日志.md