1.新增流程定义查询

2.调整流程引擎js逻辑
This commit is contained in:
wanggeng 2021-12-08 11:56:39 +08:00
parent dd04255ea4
commit 6d4647f557
17 changed files with 1321 additions and 869 deletions

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import ink.wgink.common.base.DefaultBaseController;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.module.activiti.pojo.vos.ActivitiModelVO;
import ink.wgink.module.activiti.service.activiti.IActivitiModelService;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResult;
@ -42,15 +43,14 @@ public class ActivitiModelController extends DefaultBaseController {
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PutMapping("save/{modelId}")
public SuccessResult saveModel(@PathVariable String modelId, String name, String description, String json_xml, String svg_xml) throws Exception {
name = name.trim().replace("\\s", "");
if (StringUtils.isBlank(name)) {
public SuccessResult saveModel(@PathVariable String modelId, @RequestBody ActivitiModelVO activitiModelVO) throws Exception {
if (StringUtils.isBlank(activitiModelVO.getName())) {
throw new ParamsException("名称不能为空");
}
if (RegexUtil.isChinese(name)) {
if (RegexUtil.isChinese(activitiModelVO.getName())) {
throw new ParamsException("名称不能有中文");
}
activitiModelService.saveModel(modelId, name, description, json_xml, svg_xml);
activitiModelService.saveModel(modelId, activitiModelVO.getName(), activitiModelVO.getDescription(), activitiModelVO.getJsonXml(), activitiModelVO.getSvgXml());
return new SuccessResult();
}

View File

@ -0,0 +1,44 @@
package ink.wgink.module.activiti.controller.api;
import ink.wgink.common.base.DefaultBaseController;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.module.activiti.pojo.dtos.ActivitiProcdefDTO;
import ink.wgink.module.activiti.service.activiti.IActivitiProcdefService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResultList;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @ClassName: ActivitiProcdefController
* @Description: 流程定义
* @Author: wanggeng
* @Date: 2021/12/7 10:14 PM
* @Version: 1.0
*/
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "流程定义接口")
@RestController
@RequestMapping(ISystemConstant.API_PREFIX + "/activiti/procdef")
public class ActivitiProcdefController extends DefaultBaseController {
@Autowired
private IActivitiProcdefService activitiProcdefService;
@ApiOperation(value = "部署分页列表", notes = "部署分页列表接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "Integer", defaultValue = "1"),
@ApiImplicitParam(name = "rows", value = "显示数量", paramType = "query", dataType = "Integer", defaultValue = "20"),
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("listpage")
public SuccessResultList<List<ActivitiProcdefDTO>> listPage(ListPage page) {
return activitiProcdefService.listPage(page.getPage(), page.getRows());
}
}

View File

@ -0,0 +1,28 @@
package ink.wgink.module.activiti.controller.route;
import ink.wgink.interfaces.consts.ISystemConstant;
import io.swagger.annotations.Api;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* @ClassName: ActivitiProcdefRouteController
* @Description: 流程定义
* @Author: wanggeng
* @Date: 2021/12/7 10:26 PM
* @Version: 1.0
*/
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "流程定义路由")
@Controller
@RequestMapping(ISystemConstant.ROUTE_PREFIX + "/activiti/procdef")
public class ActivitiProcdefRouteController {
@GetMapping("list")
public ModelAndView list() {
ModelAndView mv = new ModelAndView("activiti/procdef/list");
return mv;
}
}

View File

@ -0,0 +1,114 @@
package ink.wgink.module.activiti.pojo.dtos;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName: ActivitiProcdefDTO
* @Description: 流程定义
* @Author: wanggeng
* @Date: 2021/12/7 10:47 PM
* @Version: 1.0
*/
public class ActivitiProcdefDTO {
private String id;
private String name;
private String description;
private String key;
private int version;
private String category;
private String deploymentId;
private String resourceName;
private String diagramResourceName;
private Map<String, Object> variables;
private boolean hasStartFormKey;
public String getId() {
return id == null ? "" : id.trim();
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name == null ? "" : name.trim();
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description == null ? "" : description.trim();
}
public void setDescription(String description) {
this.description = description;
}
public String getKey() {
return key == null ? "" : key.trim();
}
public void setKey(String key) {
this.key = key;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public String getCategory() {
return category == null ? "" : category.trim();
}
public void setCategory(String category) {
this.category = category;
}
public String getDeploymentId() {
return deploymentId == null ? "" : deploymentId.trim();
}
public void setDeploymentId(String deploymentId) {
this.deploymentId = deploymentId;
}
public String getResourceName() {
return resourceName == null ? "" : resourceName.trim();
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
public String getDiagramResourceName() {
return diagramResourceName == null ? "" : diagramResourceName.trim();
}
public void setDiagramResourceName(String diagramResourceName) {
this.diagramResourceName = diagramResourceName;
}
public Map<String, Object> getVariables() {
return variables == null ? new HashMap<>() : variables;
}
public void setVariables(Map<String, Object> variables) {
this.variables = variables;
}
public boolean isHasStartFormKey() {
return hasStartFormKey;
}
public void setHasStartFormKey(boolean hasStartFormKey) {
this.hasStartFormKey = hasStartFormKey;
}
}

View File

@ -0,0 +1,49 @@
package ink.wgink.module.activiti.pojo.vos;
/**
* @ClassName: ActivitiModelVO
* @Description: 模型
* @Author: wanggeng
* @Date: 2021/12/7 11:36 PM
* @Version: 1.0
*/
public class ActivitiModelVO {
private String name;
private String description;
private String jsonXml;
private String svgXml;
public String getName() {
return name == null ? "" : name.trim();
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description == null ? "" : description.trim();
}
public void setDescription(String description) {
this.description = description;
}
public String getJsonXml() {
return jsonXml == null ? "" : jsonXml.trim();
}
public void setJsonXml(String jsonXml) {
this.jsonXml = jsonXml;
}
public String getSvgXml() {
return svgXml == null ? "" : svgXml.trim();
}
public void setSvgXml(String svgXml) {
this.svgXml = svgXml;
}
}

View File

@ -1,7 +1,6 @@
package ink.wgink.module.activiti.pojo.vos;
import ink.wgink.annotation.CheckEmptyAnnotation;
import ink.wgink.annotation.CheckNumberAnnotation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -26,9 +25,6 @@ public class ActivitiVO {
private String modelKey;
@ApiModelProperty(name = "modelDescription", value = "模型描述")
private String modelDescription;
@ApiModelProperty(name = "modelVersion", value = "模型版本")
@CheckNumberAnnotation(name = "模型版本")
private Integer modelVersion;
public String getModelName() {
return modelName == null ? "" : modelName.trim().replaceAll("\\s", "");
@ -53,12 +49,4 @@ public class ActivitiVO {
public void setModelDescription(String modelDescription) {
this.modelDescription = modelDescription;
}
public Integer getModelVersion() {
return modelVersion;
}
public void setModelVersion(Integer modelVersion) {
this.modelVersion = modelVersion;
}
}

View File

@ -0,0 +1,19 @@
package ink.wgink.module.activiti.service.activiti;
import ink.wgink.module.activiti.pojo.dtos.ActivitiProcdefDTO;
import ink.wgink.pojo.result.SuccessResultList;
import java.util.List;
/**
* @ClassName: IActivitiDeploymentService
* @Description: 流程定义
* @Author: wanggeng
* @Date: 2021/12/7 10:11 PM
* @Version: 1.0
*/
public interface IActivitiProcdefService {
SuccessResultList<List<ActivitiProcdefDTO>> listPage(int page, int rows);
}

View File

@ -67,5 +67,4 @@ public interface IActivitiService {
*/
SuccessResultList<List<Model>> listPage(int page, int rows);
}

View File

@ -1,9 +1,9 @@
package ink.wgink.module.activiti.service.activiti.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.exceptions.base.SystemException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.module.activiti.service.activiti.IActivitiModelService;
@ -29,7 +29,10 @@ import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
@ -58,15 +61,13 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct
if (model == null) {
throw new SearchException("模型不存在");
}
if (!StringUtils.isBlank(model.getDeploymentId())) {
throw new UpdateException("已经部署的流程无法编辑");
}
JSONObject modelObject = JSONObject.parseObject(model.getMetaInfo());
JSONObject modelObject = JSONObject.parseObject(model.getMetaInfo());
modelObject.put(MODEL_NAME, name);
modelObject.put(MODEL_DESCRIPTION, description);
model.setMetaInfo(modelObject.toString());
model.setName(name);
model.setVersion(model.getVersion() + 1);
repositoryService.saveModel(model);
repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes(ISystemConstant.CHARSET_UTF8));
@ -115,7 +116,15 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct
} catch (IOException e) {
throw e;
}
return JSONObject.parseObject(content);
JSONObject jsonObject = JSONObject.parseObject(content);
// 设置默认且唯一的信息
JSONArray propertyPackagesJsonArray = jsonObject.getJSONArray("propertyPackages");
JSONObject processIdPackageJsonObject = propertyPackagesJsonArray.getJSONObject(0);
JSONArray processIdPackagePropertiesJsonArray = processIdPackageJsonObject.getJSONArray("properties");
JSONObject processIdJsonObject = processIdPackagePropertiesJsonArray.getJSONObject(0);
processIdJsonObject.put("value", "P" + System.currentTimeMillis());
return jsonObject;
}
@Override
@ -282,4 +291,5 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct
return new ArrayList<>(flowSet);
}
}

View File

@ -0,0 +1,44 @@
package ink.wgink.module.activiti.service.activiti.impl;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.module.activiti.pojo.dtos.ActivitiProcdefDTO;
import ink.wgink.module.activiti.service.activiti.IActivitiProcdefService;
import ink.wgink.pojo.result.SuccessResultList;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: ActivitiProcdefServiceImpl
* @Description: 流程定义
* @Author: wanggeng
* @Date: 2021/12/7 10:11 PM
* @Version: 1.0
*/
@Service
public class ActivitiProcdefServiceImpl extends DefaultBaseService implements IActivitiProcdefService {
@Autowired
private RepositoryService repositoryService;
@Override
public SuccessResultList<List<ActivitiProcdefDTO>> listPage(int page, int rows) {
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
List<ProcessDefinition> processDefinitions = processDefinitionQuery.listPage(page - 1, rows);
List<ActivitiProcdefDTO> activitiProcdefDTOs = new ArrayList<>();
processDefinitions.forEach(processDefinition -> {
ActivitiProcdefDTO activitiProcdefDTO = new ActivitiProcdefDTO();
BeanUtils.copyProperties(processDefinition, activitiProcdefDTO);
activitiProcdefDTOs.add(activitiProcdefDTO);
});
return new SuccessResultList<>(activitiProcdefDTOs, page, processDefinitionQuery.count());
}
}

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.RemoveException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.module.activiti.pojo.vos.ActivitiVO;
@ -18,7 +19,7 @@ import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -48,7 +49,7 @@ public class ActivitiServiceImpl extends DefaultBaseService implements IActiviti
@Override
public String create(ActivitiVO activitiVO) throws UnsupportedEncodingException {
long count = repositoryService.createModelQuery().modelName(activitiVO.getModelName()).modelKey(activitiVO.getModelKey()).modelVersion(activitiVO.getModelVersion()).count();
long count = repositoryService.createModelQuery().modelName(activitiVO.getModelName()).modelKey(activitiVO.getModelKey()).count();
if (count >= 1) {
throw new SearchException("模型已经存在");
}
@ -56,6 +57,7 @@ public class ActivitiServiceImpl extends DefaultBaseService implements IActiviti
model.setName(activitiVO.getModelName());
model.setKey(activitiVO.getModelKey());
model.setMetaInfo(createModelMetaInfo(activitiVO));
model.setVersion(1);
LOG.debug("保存模型");
repositoryService.saveModel(model);
addModelEditorSource(model.getId());
@ -68,13 +70,9 @@ public class ActivitiServiceImpl extends DefaultBaseService implements IActiviti
if (model == null) {
throw new SearchException("模型不存在");
}
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processDefinitionKey(model.getKey()).singleResult();
// 删除模型实例
if (processInstance != null) {
runtimeService.deleteProcessInstance(processInstance.getId(), "");
historyService.deleteHistoricProcessInstance(processInstance.getId());
if (!StringUtils.isBlank(model.getDeploymentId())) {
throw new RemoveException("已部署的模型不能删除");
}
//删除模型模型
repositoryService.deleteModel(modelId);
}
@ -93,7 +91,7 @@ public class ActivitiServiceImpl extends DefaultBaseService implements IActiviti
Deployment deployment = repositoryService.createDeployment()
.name(model.getName())
.key(model.getKey())
.addBpmnModel(model.getKey() + ".bpmn20.xml", bpmnModel)
.addBpmnModel(model.getKey() + "." + model.getVersion() + ".bpmn20.xml", bpmnModel)
.deploy();
model.setDeploymentId(deployment.getId());
repositoryService.saveModel(model);
@ -109,7 +107,7 @@ public class ActivitiServiceImpl extends DefaultBaseService implements IActiviti
* 参数不加true:为普通删除如果当前规则下有正在执行的流程则抛异常
* 参数加true:为级联删除,会删除和当前规则相关的所有信息包括历史
*/
repositoryService.deleteDeployment(modelData.getDeploymentId(), true);
repositoryService.deleteDeployment(modelData.getDeploymentId());
}
@Override
@ -134,7 +132,6 @@ public class ActivitiServiceImpl extends DefaultBaseService implements IActiviti
JSONObject metaInfo = new JSONObject();
metaInfo.put(ModelDataJsonConstants.MODEL_NAME, activitiVO.getModelName());
metaInfo.put(ModelDataJsonConstants.MODEL_DESCRIPTION, activitiVO.getModelDescription());
metaInfo.put(ModelDataJsonConstants.MODEL_REVISION, activitiVO.getModelVersion());
return metaInfo.toString();
}

View File

@ -21,15 +21,64 @@
var KISBPM = KISBPM || {};
KISBPM.TOOLBAR = {
ACTIONS: {
saveModel: function (services) {
var scope = services.$scope;
top.dialog.confirm('确定保存吗?', function (index) {
top.dialog.close(index);
var json = scope.editor.getJSON();
if(!json.properties.name) {
top.dialog.msg('流程的 元素名称 不能为空');
return;
}
if(json.childShapes.length == 0) {
top.dialog.msg('流程图节点不能为空');
return;
}
json = JSON.stringify(json);
var selection = scope.editor.getSelection();
scope.editor.setSelection([]);
// Get the serialized svg image source
var svgClone = scope.editor.getCanvas().getSVGRepresentation(true);
scope.editor.setSelection(selection);
if (scope.editor.getCanvas().properties["oryx-showstripableelements"] === false) {
var stripOutArray = jQuery(svgClone).find(".stripable-element");
for (var i = stripOutArray.length - 1; i >= 0; i--) {
stripOutArray[i].remove();
}
}
// Remove all forced stripable elements
var stripOutArray = jQuery(svgClone).find(".stripable-element-force");
for (var i = stripOutArray.length - 1; i >= 0; i--) {
stripOutArray[i].remove();
}
// Parse dom to string
var svgDOM = DataManager.serialize(svgClone);
var modal = services.$modal({
backdrop: true,
keyboard: true,
template: 'editor-app/popups/save-model.html?version=' + Date.now(),
scope: services.$scope
});
var modelMetaData = scope.editor.getModelMetaData();
var params = {
jsonXml: json,
svgXml: svgDOM,
name: modelMetaData.name,
description: modelMetaData.description
};
var loadLayerIndex;
top.restAjax.put(KISBPM.URL.putModel(modelMetaData.modelId), params, null, function (code, data) {
parent.layer.close(parent.layer.getFrameIndex(window.name));
top.dialog.msg('保存成功');
}, function (code, data) {
top.dialog.msg(data.msg);
}, function () {
loadLayerIndex = top.dialog.msg(top.dataMessage.committing, {icon: 16, time: 0, shade: 0.3});
}, function () {
top.dialog.close(loadLayerIndex);
});
})
// var modal = services.$modal({
// backdrop: true,
// keyboard: true,
// template: 'editor-app/popups/save-model.html?version=' + Date.now(),
// scope: services.$scope
// });
},
undo: function (services) {
@ -43,37 +92,34 @@ KISBPM.TOOLBAR = {
// Force refresh of selection, might be that the undo command
// impacts properties in the selected item
if (services.$rootScope && services.$rootScope.forceSelectionRefresh)
{
services.$rootScope.forceSelectionRefresh = true;
if (services.$rootScope && services.$rootScope.forceSelectionRefresh) {
services.$rootScope.forceSelectionRefresh = true;
}
// Rollback every command
for (var i = lastCommands.length - 1; i >= 0; --i) {
lastCommands[i].rollback();
}
// Update and refresh the canvas
services.$scope.editor.handleEvents({
type: ORYX.CONFIG.EVENT_UNDO_ROLLBACK,
commands: lastCommands
});
// Update
services.$scope.editor.getCanvas().update();
services.$scope.editor.updateSelection();
}
var toggleUndo = false;
if (services.$scope.undoStack.length == 0)
{
toggleUndo = true;
if (services.$scope.undoStack.length == 0) {
toggleUndo = true;
}
var toggleRedo = false;
if (services.$scope.redoStack.length > 0)
{
toggleRedo = true;
if (services.$scope.redoStack.length > 0) {
toggleRedo = true;
}
if (toggleUndo || toggleRedo) {
@ -83,8 +129,7 @@ KISBPM.TOOLBAR = {
services.$scope.safeApply(function () {
item.enabled = false;
});
}
else if (toggleRedo && item.action === 'KISBPM.TOOLBAR.ACTIONS.redo') {
} else if (toggleRedo && item.action === 'KISBPM.TOOLBAR.ACTIONS.redo') {
services.$scope.safeApply(function () {
item.enabled = true;
});
@ -101,12 +146,11 @@ KISBPM.TOOLBAR = {
if (lastCommands) {
// Add this commands to the undo stack
services.$scope.undoStack.push(lastCommands);
// Force refresh of selection, might be that the redo command
// impacts properties in the selected item
if (services.$rootScope && services.$rootScope.forceSelectionRefresh)
{
services.$rootScope.forceSelectionRefresh = true;
if (services.$rootScope && services.$rootScope.forceSelectionRefresh) {
services.$rootScope.forceSelectionRefresh = true;
}
// Execute those commands
@ -142,8 +186,7 @@ KISBPM.TOOLBAR = {
services.$scope.safeApply(function () {
item.enabled = true;
});
}
else if (toggleRedo && item.action === 'KISBPM.TOOLBAR.ACTIONS.redo') {
} else if (toggleRedo && item.action === 'KISBPM.TOOLBAR.ACTIONS.redo') {
services.$scope.safeApply(function () {
item.enabled = false;
});
@ -190,14 +233,11 @@ KISBPM.TOOLBAR = {
var enableAdd = !dockerPlugin.enabledAdd();
dockerPlugin.setEnableAdd(enableAdd);
if (enableAdd)
{
dockerPlugin.setEnableRemove(false);
document.body.style.cursor = 'pointer';
}
else
{
document.body.style.cursor = 'default';
if (enableAdd) {
dockerPlugin.setEnableRemove(false);
document.body.style.cursor = 'pointer';
} else {
document.body.style.cursor = 'default';
}
},
@ -207,14 +247,11 @@ KISBPM.TOOLBAR = {
var enableRemove = !dockerPlugin.enabledRemove();
dockerPlugin.setEnableRemove(enableRemove);
if (enableRemove)
{
dockerPlugin.setEnableAdd(false);
document.body.style.cursor = 'pointer';
}
else
{
document.body.style.cursor = 'default';
if (enableRemove) {
dockerPlugin.setEnableAdd(false);
document.body.style.cursor = 'pointer';
} else {
document.body.style.cursor = 'default';
}
},
@ -239,32 +276,32 @@ KISBPM.TOOLBAR = {
zoomOut: function (services) {
KISBPM.TOOLBAR.ACTIONS._getOryxViewPlugin(services.$scope).zoom([1.0 - ORYX.CONFIG.ZOOM_OFFSET]);
},
zoomActual: function (services) {
KISBPM.TOOLBAR.ACTIONS._getOryxViewPlugin(services.$scope).setAFixZoomLevel(1);
},
zoomFit: function (services) {
KISBPM.TOOLBAR.ACTIONS._getOryxViewPlugin(services.$scope).zoomFitToModel();
KISBPM.TOOLBAR.ACTIONS._getOryxViewPlugin(services.$scope).zoomFitToModel();
},
alignVertical: function (services) {
KISBPM.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services.$scope).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]);
KISBPM.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services.$scope).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_MIDDLE]);
},
alignHorizontal: function (services) {
KISBPM.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services.$scope).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_CENTER]);
KISBPM.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services.$scope).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_CENTER]);
},
sameSize: function (services) {
KISBPM.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services.$scope).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_SIZE]);
KISBPM.TOOLBAR.ACTIONS._getOryxArrangmentPlugin(services.$scope).alignShapes([ORYX.CONFIG.EDITOR_ALIGN_SIZE]);
},
closeEditor: function(services) {
closeEditor: function (services) {
parent.layer.close(parent.layer.getFrameIndex(window.name));
// window.location.href = "./";
// window.location.href = "./";
},
/**
* Helper method: fetches the Oryx View plugin from the provided scope,
* if not on the scope, it is created and put on the scope for further use.
@ -275,7 +312,7 @@ KISBPM.TOOLBAR = {
}
return $scope.oryxViewPlugin;
},
_getOryxArrangmentPlugin: function ($scope) {
if ($scope.oryxArrangmentPlugin === undefined || $scope.oryxArrangmentPlugin === null) {
$scope.oryxArrangmentPlugin = new ORYX.Plugins.Arrangement($scope.editor);
@ -293,141 +330,147 @@ KISBPM.TOOLBAR = {
};
/** Custom controller for the save dialog */
var SaveModelCtrl = [ '$rootScope', '$scope', '$http', '$route', '$location',
var SaveModelCtrl = ['$rootScope', '$scope', '$http', '$route', '$location',
function ($rootScope, $scope, $http, $route, $location) {
var modelMetaData = $scope.editor.getModelMetaData();
var modelMetaData = $scope.editor.getModelMetaData();
var description = '';
if (modelMetaData.description) {
description = modelMetaData.description;
}
var saveDialog = { 'name' : modelMetaData.name,
'description' : description};
$scope.saveDialog = saveDialog;
var json = $scope.editor.getJSON();
json = JSON.stringify(json);
var params = {
modeltype: modelMetaData.model.modelType,
json_xml: json,
name: 'model'
};
$scope.status = {
loading: false
};
$scope.close = function () {
$scope.$hide();
};
$scope.saveAndClose = function () {
$scope.save(function() {
parent.layer.close(parent.layer.getFrameIndex(window.name));
// window.location.href = "./";
});
};
$scope.save = function (successCallback) {
if (!$scope.saveDialog.name || $scope.saveDialog.name.length == 0) {
return;
var description = '';
if (modelMetaData.description) {
description = modelMetaData.description;
}
// Indicator spinner image
$scope.status = {
loading: true
var saveDialog = {
'name': modelMetaData.name,
'description': description
};
modelMetaData.name = $scope.saveDialog.name;
modelMetaData.description = $scope.saveDialog.description;
$scope.saveDialog = saveDialog;
var json = $scope.editor.getJSON();
json = JSON.stringify(json);
var selection = $scope.editor.getSelection();
$scope.editor.setSelection([]);
// Get the serialized svg image source
var svgClone = $scope.editor.getCanvas().getSVGRepresentation(true);
$scope.editor.setSelection(selection);
if ($scope.editor.getCanvas().properties["oryx-showstripableelements"] === false) {
var stripOutArray = jQuery(svgClone).find(".stripable-element");
for (var i = stripOutArray.length - 1; i >= 0; i--) {
stripOutArray[i].remove();
}
}
// Remove all forced stripable elements
var stripOutArray = jQuery(svgClone).find(".stripable-element-force");
for (var i = stripOutArray.length - 1; i >= 0; i--) {
stripOutArray[i].remove();
}
// Parse dom to string
var svgDOM = DataManager.serialize(svgClone);
var params = {
modeltype: modelMetaData.model.modelType,
json_xml: json,
svg_xml: svgDOM,
name: $scope.saveDialog.name,
description: $scope.saveDialog.description
name: 'model'
};
// Update
$http({ method: 'PUT',
data: params,
ignoreErrors: true,
headers: {'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
},
url: KISBPM.URL.putModel(modelMetaData.modelId)})
$scope.status = {
loading: false
};
.success(function (data, status, headers, config) {
$scope.editor.handleEvents({
type: ORYX.CONFIG.EVENT_SAVED
});
$scope.modelData.name = $scope.saveDialog.name;
$scope.modelData.lastUpdated = data.lastUpdated;
$scope.status.loading = false;
$scope.$hide();
$scope.close = function () {
$scope.$hide();
};
// Fire event to all who is listening
var saveEvent = {
type: KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED,
model: params,
modelId: modelMetaData.modelId,
eventType: 'update-model'
};
KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED, saveEvent);
// Reset state
$scope.error = undefined;
$scope.status.loading = false;
// Execute any callback
if (successCallback) {
successCallback();
}
})
.error(function (data, status, headers, config) {
$scope.status.loading = false;
top.dialog.msg(data.msg);
// $scope.error = {};
// console.log('Something went wrong when updating the process model:' + JSON.stringify(data));
// $scope.status.loading = false;
$scope.saveAndClose = function () {
$scope.save(function () {
parent.layer.close(parent.layer.getFrameIndex(window.name));
// window.location.href = "./";
});
};
};
$scope.save = function (successCallback) {
}];
if (!$scope.saveDialog.name || $scope.saveDialog.name.length == 0) {
return;
}
// Indicator spinner image
$scope.status = {
loading: true
};
modelMetaData.name = $scope.saveDialog.name;
modelMetaData.description = $scope.saveDialog.description;
var json = $scope.editor.getJSON();
json = JSON.stringify(json);
var selection = $scope.editor.getSelection();
$scope.editor.setSelection([]);
// Get the serialized svg image source
var svgClone = $scope.editor.getCanvas().getSVGRepresentation(true);
$scope.editor.setSelection(selection);
if ($scope.editor.getCanvas().properties["oryx-showstripableelements"] === false) {
var stripOutArray = jQuery(svgClone).find(".stripable-element");
for (var i = stripOutArray.length - 1; i >= 0; i--) {
stripOutArray[i].remove();
}
}
// Remove all forced stripable elements
var stripOutArray = jQuery(svgClone).find(".stripable-element-force");
for (var i = stripOutArray.length - 1; i >= 0; i--) {
stripOutArray[i].remove();
}
// Parse dom to string
var svgDOM = DataManager.serialize(svgClone);
var params = {
json_xml: json,
svg_xml: svgDOM,
name: $scope.saveDialog.name,
description: $scope.saveDialog.description
};
// Update
$http({
method: 'PUT',
data: params,
ignoreErrors: true,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
transformRequest: function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
},
url: KISBPM.URL.putModel(modelMetaData.modelId)
})
.success(function (data, status, headers, config) {
$scope.editor.handleEvents({
type: ORYX.CONFIG.EVENT_SAVED
});
$scope.modelData.name = $scope.saveDialog.name;
$scope.modelData.lastUpdated = data.lastUpdated;
$scope.status.loading = false;
$scope.$hide();
// Fire event to all who is listening
var saveEvent = {
type: KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED,
model: params,
modelId: modelMetaData.modelId,
eventType: 'update-model'
};
KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED, saveEvent);
// Reset state
$scope.error = undefined;
$scope.status.loading = false;
// Execute any callback
if (successCallback) {
successCallback();
}
})
.error(function (data, status, headers, config) {
$scope.status.loading = false;
top.dialog.msg(data.msg);
// $scope.error = {};
// console.log('Something went wrong when updating the process model:' + JSON.stringify(data));
// $scope.status.loading = false;
});
};
}];

View File

@ -9,8 +9,8 @@
{
"id": "process_id",
"type": "String",
"title": "流程名称",
"value": "process",
"title": "流程ID",
"value": "",
"description": "流程的特殊唯一的名称标识",
"popular": true
}
@ -35,7 +35,7 @@
{
"id": "name",
"type": "String",
"title": "名称",
"title": "元素名称",
"value": "",
"description": "元素名称",
"popular": true,

View File

@ -122,15 +122,12 @@
if(!row.deploymentId) {
return '-';
}
return '<button class="layui-btn layui-btn-sm" lay-event="flowChatEvent">查看</button>';
return '<button class="layui-btn layui-btn-xs" lay-event="flowChatEvent">查看</button>';
}
},
{field: 'option', width: 80, title: '操作', align:'center', fixed: 'right',
{field: 'option2', width: 80, title: '操作', align:'center', fixed: 'right',
templet: function(row) {
if(!row.deploymentId) {
return '<button class="layui-btn layui-btn-normal layui-btn-sm" lay-event="publishEvent">部署</button>';
}
return '<button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="revokePublishEvent">撤销</button>';
return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="publishEvent">部署</button>';
}
},
]
@ -212,10 +209,6 @@
} else if(checkDatas.length > 1) {
top.dialog.msg(top.dataMessage.table.selectOneEdit);
} else {
if(checkDatas[0].deploymentId) {
top.dialog.msg('已经部署的流程不能编辑');
return;
}
top.dialog.open({
url: top.restAjax.path('route/activiti/update?modelId={modelId}', [checkDatas[0].id]),
title: false,
@ -255,21 +248,6 @@
top.dialog.close(loadLayerIndex);
});
});
} else if(layEvent === 'revokePublishEvent') {
top.dialog.confirm('确定 撤销 部署流程?', function(index) {
top.dialog.close(index);
var loadLayerIndex;
top.restAjax.put(top.restAjax.path('api/activiti/revoke-publish/{modelId}', [data.id]), {}, null, function(code, data) {
top.dialog.msg('操作成功');
reloadTable();
}, function(code, data) {
top.dialog.msg(data.msg);
}, function() {
loadLayerIndex = top.dialog.msg(top.dataMessage.committing, {icon: 16, time: 0, shade: 0.3});
}, function() {
top.dialog.close(loadLayerIndex);
});
});
} else if(layEvent === 'flowChatEvent') {
if(!data.deploymentId) {
top.dialog.msg('流程未部署,无法查看流程图');

View File

@ -0,0 +1,197 @@
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<base th:href="${#request.getContextPath() + '/'} ">
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/fonts/font-awesome/css/font-awesome.css"/>
<link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
<link rel="stylesheet" href="assets/layuiadmin/style/admin.css" media="all">
</head>
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-row">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-body">
<table class="layui-hide" id="dataTable" lay-filter="dataTable"></table>
</div>
</div>
</div>
</div>
</div>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script src="assets/js/vendor/viewer/viewer.min.js"></script>
<script>
layui.config({
base: 'assets/layuiadmin/'
}).extend({
index: 'lib/index'
}).use(['index', 'table', 'laydate', 'common'], function() {
var $ = layui.$;
var $win = $(window);
var table = layui.table;
var admin = layui.admin;
var laydate = layui.laydate;
var common = layui.common;
var resizeTimeout = null;
var tableUrl = 'api/activiti/procdef/listpage';
// 初始化表格
function initTable() {
table.render({
elem: '#dataTable',
id: 'dataTable',
url: top.restAjax.path(tableUrl, []),
width: admin.screen() > 1 ? '100%' : '',
height: $win.height() - 50,
limit: 20,
limits: [20, 40, 60, 80, 100, 200],
request: {
pageName: 'page',
limitName: 'rows'
},
cols: [
[
{field:'rowNum', width:80, title: '序号', fixed: 'left', align:'center', templet: '<span>{{d.LAY_INDEX}}</span>'},
{field:'id', width:150, title: '主键', align:'center',
templet: function(row) {
var rowData = row[this.field];
if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field:'key', width:150, title: '流程定义ID', align:'center',
templet: function(row) {
var rowData = row[this.field];
if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field:'version', width:80, title: '版本', align:'center',
templet: function(row) {
var rowData = row[this.field];
if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field:'name', width:150, title: '名称', align:'center',
templet: function(row) {
var rowData = row[this.field];
if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field:'description', width:150, title: '描述', align:'center',
templet: function(row) {
var rowData = row[this.field];
if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field:'deploymentId', width:150, title: '部署ID', align:'center',
templet: function(row) {
var rowData = row[this.field];
if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field:'category', width:150, title: '目录名称', align:'center',
templet: function(row) {
var rowData = row[this.field];
if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field:'resourceName', width:200, title: '流程资源名称', align:'center',
templet: function(row) {
var rowData = row[this.field];
if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field: 'diagramResourceName', width: 80, title: '流程图', align:'center', fixed: 'right',
templet: function(row) {
if(!row.deploymentId) {
return '-';
}
return '<button class="layui-btn layui-btn-xs" lay-event="flowChatEvent">查看</button>';
}
}
]
],
page: true,
parseData: function(data) {
return {
'code': 0,
'msg': '',
'count': data.total,
'data': data.rows
};
}
});
}
// 重载表格
function reloadTable(currentPage) {
table.reload('dataTable', {
url: top.restAjax.path(tableUrl, []),
where: {},
page: {
curr: currentPage
},
height: $win.height() - 50,
});
}
initTable();
// 事件 - 页面变化
$win.on('resize', function() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function() {
reloadTable();
}, 500);
});
// 事件 - 搜索
$(document).on('click', '#search', function() {
reloadTable(1);
});
table.on('tool(dataTable)', function(obj) {
var data = obj.data;
var layEvent = obj.event;
if(layEvent === 'flowChatEvent') {
if(!data.deploymentId) {
top.dialog.msg('流程未部署,无法查看流程图');
return;
}
top.dialog.open({
url: top.restAjax.path('route/activiti/get-process-image/{deploymentId}', [data.deploymentId]),
title: '流程图',
width: '800px',
height: '400px',
onClose: function() {}
});
}
});
});
</script>
</body>
</html>

View File

@ -33,13 +33,6 @@
<input type="text" id="modelDescription" name="modelDescription" class="layui-input" value="" placeholder="请输入模型描述" lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">模型版本</label>
<div class="layui-input-block">
<input type="number" id="modelVersion" name="modelVersion" class="layui-input" value="" placeholder="请输入模型版本" lay-verify="required">
</div>
</div>
<div class="layui-form-item layui-layout-admin">
<div class="layui-input-block">
<div class="layui-footer" style="left: 0;">