提交 83d49e82 编写于 作者: jwxkk's avatar jwxkk

项目初始化

上级
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
Acticiti7工作流引擎
===============
# 项目介绍
[查看本课程配套视频教程请,点这里](https://coding.imooc.com/class/454.html)
基于[Acticiti7](https://github.com/Activiti/Activiti)的Web工作流引擎,完整开源。
前端基于layuimini,[在github找到项目相关介绍](https://github.com/zhongshaofa/layuimini/releases)
# 主要特性
* 完整的流程部署、创建实例、任务流转
* 使用Acticiti7新版特性
* 融合BPMN-JS作为流程绘制工具
* 整合SpringSecurity安全框架
# 启动项目流程
### 1、windows平台获取项目
> 方案一:(使用GIT命令)
* [下载GIT](https://git-scm.com/downloads)并安装
* 新建本地文件夹
* 选中文件夹右键,输入命令,文件夹变成Git仓库 `git init`
* 复制git项目地址 `git clone https://github.com/wwdui/activiti7-workflow.git`
* 输入默课网账号密码即可下载
![Image text](./src/main/resources/static/git_show/0003.png)
> 方案二:(使用IDEA)
* [下载GIT](https://git-scm.com/downloads)并安装
* 打开IDEA,【File】->【Settings】->【Version Control】->【Path to Git executable】设置为安装后的git.exe路径
* 创建IDEA项目,【File】->【New】->【Project from Version Control】->【Git】设置URL`https://github.com/wwdui/activiti7-workflow.git`
![Image text](./src/main/resources/static/git_show/0004.png)
### 2、修改本地Maven为阿里云
* 打开IDEA,【File】->【Open】找到下载的项目中pom.xml,选择【Open as Project】
* 【File】->【Settings】->【Build,Execution,Deploymen】->【Maven】,右侧User sttings file查看“settings.xml”位置
* 打开settings.xml,找到`<mirrors>`标签,添加下面语句:
```
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里maven仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
```
* 保存后重新打开settings.xml确定保存成功
### 3、修改YML配置文件数据库连接
> 没有安装过数据库的同学也不要紧张,下一章课程会带领大家安装与配置数据库
* 打开项目文件src\main\resources\application.yml
* datasource节点配置username、password、url为自己的数据库配置信息,本项目默认使用MySQL数据库
### 4、执行user.sql创建用户表并修复Activiti7官方Bug
* 注意:先运行一次项目,Activiti会自动初始化数据库需要的表,然后再执行下面的sql
* 使用Navicat等工具执行项目根目录下user.sql
### 5、运行项目
>
测试账号:bajie
密码:1
测试账号:wukong
密码:1
* 点击IDEA右上方绿色箭头Run项目(或按Shift+F10运行项目)
* 打开浏览器输入地址localhost:8080/layuimini/page/login-1.html
# 效果预览
> 总体预览
![Image text](./src/main/resources/static/git_show/0001.jpg)
![Image text](./src/main/resources/static/git_show/0002.gif)
# 使用说明
文档地址:[查看文档待更新](https://coding.imooc.com/class/454.html)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.imooc</groupId>
<artifactId>activitiweb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>activitiweb</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M4</version>
</dependency>
<dependency>
<groupId>org.activiti.dependencies</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>7.1.0.M4</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.imooc.activitiweb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ActivitiwebApplication {
public static void main(String[] args) {
SpringApplication.run(ActivitiwebApplication.class, args);
}
}
package com.imooc.activitiweb;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
//@Configuration
public class DemoApplicationConfiguration {
private Logger logger = LoggerFactory.getLogger(DemoApplicationConfiguration.class);
// @Bean
public UserDetailsService myUserDetailsService() {
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
String[][] usersGroupsAndRoles = {
{"salaboy", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
{"bajie", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
{"wukong", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
{"other", "password", "ROLE_ACTIVITI_USER", "GROUP_otherTeam"},
{"admin", "password", "ROLE_ACTIVITI_ADMIN"},
};
for (String[] user : usersGroupsAndRoles) {
List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));
logger.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");
inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]),
authoritiesStrings.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList())));
}
return inMemoryUserDetailsManager;
}
// @Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
package com.imooc.activitiweb;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import java.util.Collection;
@Component
public class SecurityUtil {
private Logger logger = LoggerFactory.getLogger(SecurityUtil.class);
@Autowired
private UserDetailsService userDetailsService;
public void logInAs(String username) {
UserDetails user = userDetailsService.loadUserByUsername(username);
if (user == null) {
throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");
}
logger.info("> Logged in as: " + username);
SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getAuthorities();
}
@Override
public Object getCredentials() {
return user.getPassword();
}
@Override
public Object getDetails() {
return user;
}
@Override
public Object getPrincipal() {
return user;
}
@Override
public boolean isAuthenticated() {
return true;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName() {
return user.getUsername();
}
}));
org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
}
}
package com.imooc.activitiweb.controller;
import com.imooc.activitiweb.SecurityUtil;
import com.imooc.activitiweb.util.AjaxResponse;
import com.imooc.activitiweb.util.GlobalConfig;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/activitiHistory")
public class ActivitiHistoryController {
@Autowired
private SecurityUtil securityUtil;
@Autowired
private RepositoryService repositoryService;
@Autowired
private HistoryService historyService;
//用户历史
@GetMapping(value = "/getInstancesByUserName")
public AjaxResponse InstancesByUser() {
try {
List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
.orderByHistoricTaskInstanceEndTime().asc()
.taskAssignee("bajie")
.list();
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), historicTaskInstances);
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"获取历史任务失败", e.toString());
}
}
//任务实例历史
@GetMapping(value = "/getInstancesByPiID")
public AjaxResponse getInstancesByPiID(@RequestParam("piID") String piID) {
try {
//--------------------------------------------另一种写法-------------------------
List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
.orderByHistoricTaskInstanceEndTime().asc()
.processInstanceId(piID)
.list();
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), historicTaskInstances);
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"获取历史任务失败", e.toString());
}
}
//流程图高亮
@RequestMapping("/highLine")
@ResponseBody
public Map<String,Object> getApplyStatus(String instanceId){
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(instanceId).singleResult();
//获取bpmnModel对象
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
//因为我们这里只定义了一个Process 所以获取集合中的第一个即可
Process process = bpmnModel.getProcesses().get(0);
//获取所有的FlowElement信息
Collection<FlowElement> flowElements = process.getFlowElements();
Map<String,String> map = new HashMap<>();
for (FlowElement flowElement : flowElements) {
//判断是否是连线
if (flowElement instanceof SequenceFlow) {
SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
String ref = sequenceFlow.getSourceRef();
String targetRef = sequenceFlow.getTargetRef();
map.put(ref+targetRef,sequenceFlow.getId());
}
}
//获取流程实例 历史节点(全部)
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(instanceId)
.list();
//各个历史节点 两两组合 key
Set<String> keyList = new HashSet<>();
for (HistoricActivityInstance i: list) {
for(HistoricActivityInstance j : list){
if(i!=j){
keyList.add(i.getActivityId()+j.getActivityId());
}
}
}
//高亮连线ID
Set<String> highLine = new HashSet<>();
keyList.forEach(s->highLine.add(map.get(s)));
//获取流程实例 历史节点(已完成)
List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(instanceId)
.finished()
.list();
//高亮节点ID
Set<String> highPoint = new HashSet<>();
listFinished.forEach(s->highPoint.add(s.getActivityId()));
//获取流程实例 历史节点(待办节点)
List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(instanceId)
.unfinished()
.list();
//需要移除的高亮连线
Set<String> set = new HashSet<>();
//待办高亮节点
Set<String> waitingToDo = new HashSet<>();
listUnFinished.forEach(s->{
waitingToDo.add(s.getActivityId());
for (FlowElement flowElement : flowElements) {
//判断是否是 用户节点
if (flowElement instanceof UserTask) {
UserTask userTask = (UserTask) flowElement;
if(userTask.getId().equals(s.getActivityId())){
List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
//因为 高亮连线查询的是所有节点 两两组合 把待办 之后 往外发出的连线 也包含进去了 所以要把高亮待办节点 之后 即出的连线去掉
if(outgoingFlows!=null&& outgoingFlows.size()>0){
outgoingFlows.forEach(a-> {
if(a.getSourceRef().equals(s.getActivityId())){
set.add(a.getId());
}
});
}
}
}
}
});
highLine.removeAll(set);
//获取当前用户
//User sysUser = getSysUser();
Set<String> iDo = new HashSet<>(); //存放 高亮 我的办理节点
//当前用户已完成的任务
List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery()
.taskAssignee("bajie")
.finished()
.processInstanceId(instanceId).list();
taskInstanceList.forEach(a->iDo.add(a.getTaskDefinitionKey()));
Map<String,Object> reMap = new HashMap<>();
reMap.put("highPoint",highPoint);
reMap.put("highLine",highLine);
reMap.put("waitingToDo",waitingToDo);
reMap.put("iDo",iDo);
return reMap;
}
}
package com.imooc.activitiweb.controller;
import com.imooc.activitiweb.SecurityUtil;
import com.imooc.activitiweb.mapper.ActivitiMapper;
import com.imooc.activitiweb.pojo.UserInfoBean;
import com.imooc.activitiweb.pojo.Act_ru_task;
import com.imooc.activitiweb.util.AjaxResponse;
import com.imooc.activitiweb.util.GlobalConfig;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.runtime.TaskRuntime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class HelloController {
@Autowired
private TaskRuntime taskRuntime;
@Autowired
private SecurityUtil securityUtil;
@Autowired
ActivitiMapper mapper;
@Autowired
private ProcessRuntime processRuntime;
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String say() {
return "你好";
}
@RequestMapping(value = "/me1", method = RequestMethod.GET)
public Object getCurrentUser() {
return SecurityContextHolder.getContext().getAuthentication().getName();
}
@RequestMapping(value = "/me2", method = RequestMethod.GET)
public Object user(@AuthenticationPrincipal UserInfoBean UuserInfoBean){
return UuserInfoBean.name;
}
@RequestMapping(value = "/task", method = RequestMethod.GET)
public Object gettask() {
String userName=SecurityContextHolder.getContext().getAuthentication().getName();
securityUtil.logInAs(userName);
try {
Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 10));
return "> Other cannot see the task: " + tasks.getTotalItems();
} catch (Exception e) {
return "错误:" + e;
}
}
@RequestMapping(value = "/db", method = RequestMethod.GET)
public Object getdb() {
try {
List<Act_ru_task> act_ru_task123 = mapper.selectName();
return act_ru_task123.toString();
} catch (Exception e) {
return "错误:" + e;
}
}
//启动带参数---------------测试方法-----------------------
@GetMapping(value = "/testStartProcess")
public AjaxResponse testStartProcess(@RequestParam("processDefinitionKey") String processDefinitionKey,
@RequestParam("instanceName") String instanceName) {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("bajie");
}else{
securityUtil.logInAs(SecurityContextHolder.getContext().getAuthentication().getName());
}
ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
.start()
.withProcessDefinitionKey(processDefinitionKey)
.withName(instanceName)
.withVariable("assignee", "bajie")
.withBusinessKey("自定义BusinessKey")
.build());
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName()+";"+processInstance.getId());
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"创建流程实例失败", e.toString());
}
}
}
package com.imooc.activitiweb.controller;
import com.imooc.activitiweb.SecurityUtil;
import com.imooc.activitiweb.util.AjaxResponse;
import com.imooc.activitiweb.util.GlobalConfig;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/processDefinition")
public class ProcessDefinitionController {
@Autowired
private RepositoryService repositoryService;
@Autowired
private ProcessRuntime processRuntime;
@Autowired
private SecurityUtil securityUtil;
@PostMapping(value = "/uploadStreamAndDeployment")
public AjaxResponse uploadStreamAndDeployment(@RequestParam("processFile") MultipartFile multipartFile) {
// 获取上传的文件名
String fileName = multipartFile.getOriginalFilename();
try {
// 得到输入流(字节流)对象
InputStream fileInputStream = multipartFile.getInputStream();
// 文件的扩展名
String extension = FilenameUtils.getExtension(fileName);
// ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//创建处理引擎实例
// repositoryService = processEngine.getRepositoryService();//创建仓库服务实例
Deployment deployment = null;
if (extension.equals("zip")) {
ZipInputStream zip = new ZipInputStream(fileInputStream);
deployment = repositoryService.createDeployment()//初始化流程
.addZipInputStream(zip)
.name("流程部署名称可通过接口传递现在写死")
.deploy();
} else {
deployment = repositoryService.createDeployment()//初始化流程
.addInputStream(fileName, fileInputStream)
.name("流程部署名称可通过接口传递现在写死")
.deploy();
}
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), deployment.getId()+";"+fileName);
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"部署流程失败", e.toString());
}
//return AjaxResponse.AjaxData(1,"成功",fileName);
}
@PostMapping(value = "/upload")
public AjaxResponse upload(HttpServletRequest request, @RequestParam("processFile") MultipartFile multipartFile) {
if (multipartFile.isEmpty()) {
System.out.println("文件为空");
}
String fileName = multipartFile.getOriginalFilename(); // 文件名
String suffixName = fileName.substring(fileName.lastIndexOf(".")); // 后缀名
String filePath = GlobalConfig.BPMN_PathMapping; // 上传后的路径
//本地路径格式转上传路径格式
filePath = filePath.replace("\\", "/");
filePath = filePath.replace("file:", "");
// String filePath = request.getSession().getServletContext().getRealPath("/") + "bpmn/";
fileName = UUID.randomUUID() + suffixName; // 新文件名
File file = new File(filePath + fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try {
multipartFile.transferTo(file);
} catch (Exception e) {
System.out.println(e.toString());
}
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), fileName);
}
/**
*
* @param deploymentFileUUID
* @return
*/
@PostMapping(value = "/addDeploymentByFileNameBPMN")
public AjaxResponse addDeploymentByFileNameBPMN(@RequestParam("deploymentFileUUID") String deploymentFileUUID,@RequestParam("deploymentName") String deploymentName) {
try {
String filename = "resources/bpmn/" + deploymentFileUUID;
Deployment deployment = repositoryService.createDeployment()//初始化流程
.addClasspathResource(filename)
.name(deploymentName)
.deploy();
System.out.println(deployment.getName());
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), deployment.getId());
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"BPMN部署流程失败", e.toString());
}
}
@PostMapping(value = "/addDeploymentByString")
public AjaxResponse addDeploymentByString(@RequestParam("stringBPMN") String stringBPMN,@RequestParam("deploymentName") String deploymentName) {
try {
Deployment deployment = repositoryService.createDeployment()
.addString("OnLine.bpmn",stringBPMN)
.name(deploymentName)
.deploy();
System.out.println(deployment.getName());
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), deployment.getId());
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"string部署流程失败", e.toString());
}
}
//缺失流程部署ID属性版本,import org.activiti.api.process.model.ProcessDefinition;
/*@GetMapping(value = "/getDefinitions")
public AjaxResponse getDefinitions() {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("wukong");
}
Page<ProcessDefinition> processDefinitions = processRuntime.processDefinitions(Pageable.of(0, 50));
System.out.println("流程定义数量: " + processDefinitions.getTotalItems());
for (ProcessDefinition pd : processDefinitions.getContent()) {
System.out.println("getId:" + pd.getId());
System.out.println("getName:" + pd.getName());
System.out.println("getStatus:" + pd.getKey());
System.out.println("getStatus:" + pd.getFormKey());
}
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), processDefinitions.getContent());
}catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"获取流程定义失败", e.toString());
}
}*/
//import org.activiti.engine.RepositoryService;
@GetMapping(value = "/getDefinitions")
public AjaxResponse getDefinitions() {
try {
List<HashMap<String, Object>> listMap= new ArrayList<HashMap<String, Object>>();
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
list.sort((y,x)->x.getVersion()-y.getVersion());
for (ProcessDefinition pd : list) {
HashMap<String, Object> hashMap = new HashMap<>();
System.out.println("流程定义ID:"+pd.getId());
hashMap.put("Name", pd.getName());
hashMap.put("Key", pd.getKey());
hashMap.put("ResourceName", pd.getResourceName());
hashMap.put("DeploymentId", pd.getDeploymentId());
hashMap.put("Version", pd.getVersion());
listMap.add(hashMap);
}
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), listMap);
}catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"获取流程定义失败", e.toString());
}
}
//获取流程定义XML
@GetMapping(value = "/getDefinitionXML")
public void getProcessDefineXML(HttpServletResponse response,
@RequestParam("deploymentId") String deploymentId,
@RequestParam("resourceName") String resourceName) {
try {
InputStream inputStream = repositoryService.getResourceAsStream(deploymentId,resourceName);
int count = inputStream.available();
byte[] bytes = new byte[count];
response.setContentType("text/xml");
OutputStream outputStream = response.getOutputStream();
while (inputStream.read(bytes) != -1) {
outputStream.write(bytes);
}
inputStream.close();
} catch (Exception e) {
e.toString();
}
}
@GetMapping(value = "/getDeployments")
public AjaxResponse getDeployments() {
try {
List<HashMap<String, Object>> listMap= new ArrayList<HashMap<String, Object>>();
List<Deployment> list = repositoryService.createDeploymentQuery().list();
for (Deployment dep : list) {
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("ID", dep.getId());
hashMap.put("Name", dep.getName());
hashMap.put("DeploymentTime", dep.getDeploymentTime());
listMap.add(hashMap);
}
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), listMap);
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"查询失败", e.toString());
}
}
//删除流程定义
@GetMapping(value = "/delDefinition")
public AjaxResponse delDefinition(@RequestParam("pdID") String pdID) {
try {
repositoryService.deleteDeployment(pdID, true);
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
"删除成功", null);
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"删除失败", e.toString());
}
}
}
package com.imooc.activitiweb.controller;
import com.imooc.activitiweb.SecurityUtil;
import com.imooc.activitiweb.util.AjaxResponse;
import com.imooc.activitiweb.util.GlobalConfig;
import com.imooc.activitiweb.pojo.UserInfoBean;
import org.activiti.api.model.shared.model.VariableInstance;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/processInstance")
public class ProcessInstanceController {
@Autowired
private ProcessRuntime processRuntime;
@Autowired
private SecurityUtil securityUtil;
@GetMapping(value = "/getInstances")
public AjaxResponse getInstances(@AuthenticationPrincipal UserInfoBean userInfoBean) {
Page<ProcessInstance> processInstances = null;
try {
//测试用写死的用户POSTMAN测试用;生产场景已经登录,在processDefinitions中可以获取到当前登录用户的信息
if (GlobalConfig.Test) {
securityUtil.logInAs("wukong");
}
//else {
// securityUtil.logInAs(userInfoBean.getUsername());//这句不需要
// }
processInstances=processRuntime.processInstances(Pageable.of(0, 50));
System.out.println("流程实例数量: " + processInstances.getTotalItems());
List<ProcessInstance> list = processInstances.getContent();
//list.sort((y,x)->x.getProcessDefinitionVersion()-y.getProcessDefinitionVersion());
list.sort((y,x)->x.getStartDate().toString().compareTo(y.getStartDate().toString()));
for(ProcessInstance pi:list){
System.out.println("getId:"+pi.getId());
System.out.println("getName:"+pi.getName());
System.out.println("getStatus:"+pi.getStatus());
System.out.println("getProcessDefinitionId:"+pi.getProcessDefinitionId());
System.out.println("getProcessDefinitionKey:"+pi.getProcessDefinitionKey());
System.out.println("getStartDate:"+pi.getStartDate());
}
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(),processInstances.getContent());
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"获取流程实例失败", e.toString());
}
}
//启动
@GetMapping(value = "/startProcess")
public AjaxResponse startProcess(@RequestParam("processDefinitionKey") String processDefinitionKey,
@RequestParam("instanceName") String instanceName,
@RequestParam("instanceVariable") String instanceVariable) {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("bajie");
}else{
securityUtil.logInAs(SecurityContextHolder.getContext().getAuthentication().getName());
}
ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
.start()
.withProcessDefinitionKey(processDefinitionKey)
.withName(instanceName)
.withVariable("content", instanceVariable)
.withVariable("参数2", "参数2的值")
.withBusinessKey("自定义BusinessKey")
.build());
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName()+";"+processInstance.getId());
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"创建流程实例失败", e.toString());
}
}
//删除
@GetMapping(value = "/deleteInstance")
public AjaxResponse deleteInstance(@RequestParam("instanceID") String instanceID) {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("wukong");
}
ProcessInstance processInstance = processRuntime.delete(ProcessPayloadBuilder
.delete()
.withProcessInstanceId(instanceID)
.build()
);
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName());
}
catch(Exception e)
{
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"删除流程实例失败", e.toString());
}
}
//挂起冷冻
@GetMapping(value = "/suspendInstance")
public AjaxResponse suspendInstance(@RequestParam("instanceID") String instanceID) {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("wukong");
}
ProcessInstance processInstance = processRuntime.suspend(ProcessPayloadBuilder
.suspend()
.withProcessInstanceId(instanceID)
.build()
);
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName());
}
catch(Exception e)
{
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"挂起流程实例失败", e.toString());
}
}
//激活
@GetMapping(value = "/resumeInstance")
public AjaxResponse resumeInstance(@RequestParam("instanceID") String instanceID) {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("wukong");
}
ProcessInstance processInstance = processRuntime.resume(ProcessPayloadBuilder
.resume()
.withProcessInstanceId(instanceID)
.build()
);
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName());
}
catch(Exception e)
{
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"激活流程实例失败", e.toString());
}
}
//获取参数
@GetMapping(value = "/variables")
public AjaxResponse variables(@RequestParam("instanceID") String instanceID) {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("wukong");
}
List<VariableInstance> variableInstance = processRuntime.variables(ProcessPayloadBuilder
.variables()
.withProcessInstanceId(instanceID)
.build());
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), variableInstance);
}
catch(Exception e)
{
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"获取流程参数失败", e.toString());
}
}
}
package com.imooc.activitiweb.controller;
import com.imooc.activitiweb.SecurityUtil;
import com.imooc.activitiweb.util.AjaxResponse;
import com.imooc.activitiweb.util.GlobalConfig;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@RestController
@RequestMapping("/task")
public class TaskController {
@Autowired
private TaskRuntime taskRuntime;
@Autowired
private SecurityUtil securityUtil;
@Autowired
private ProcessRuntime processRuntime;
//获取我的代办任务
@GetMapping(value = "/getTasks")
public AjaxResponse getTasks() {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("wukong");
}
Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 100));
List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
for (Task tk : tasks.getContent()) {
ProcessInstance processInstance = processRuntime.processInstance(tk.getProcessInstanceId());
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("ID", tk.getId());
hashMap.put("Name", tk.getName());
hashMap.put("Status", tk.getStatus());
hashMap.put("CreatedDate", tk.getCreatedDate());
if(tk.getAssignee() == null){//执行人,null时前台显示未拾取
hashMap.put("Assignee", "待拾取任务");
}else {
hashMap.put("Assignee", tk.getAssignee());//
}
hashMap.put("InstanceName", processInstance.getName());
listMap.add(hashMap);
}
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), listMap);
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"获取我的代办任务失败", e.toString());
}
}
//完成待办任务
@GetMapping(value = "/completeTask")
public AjaxResponse completeTask(@RequestParam("taskID") String taskID) {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("bajie");
}
Task task = taskRuntime.task(taskID);
if (task.getAssignee() == null) {
taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
}
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).build());
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"完成失败", e.toString());
}
}
//启动
@GetMapping(value = "/startProcess4")
public AjaxResponse startProcess3(@RequestParam("processDefinitionKey") String processDefinitionKey,
@RequestParam("instanceName") String instanceName,
@RequestParam("instanceVariable") String instanceVariable) {
try {
if (GlobalConfig.Test) {
securityUtil.logInAs("wukong");
}
/* @RequestMapping("/approval_msg")
@ResponseBody
public JsonResponse approvalPass(String id,String msg){
JsonResponse jsonResponse = new JsonResponse();
if(StringUtil.isNotEmpty(msg)){
String str= msg.replace("\"", "");
taskService.setVariable(id,"msg",str);
}
taskService.complete(id);
return jsonResponse;
}*/
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
} catch (Exception e) {
return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
"失败", e.toString());
}
}
}
package com.imooc.activitiweb.mapper;
import com.imooc.activitiweb.pojo.Act_ru_task;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;
import java.util.List;
@Mapper
@Component
public interface ActivitiMapper {
@Select("select NAME_,TASK_DEF_KEY_ from act_ru_task")
List<Act_ru_task> selectName();
}
package com.imooc.activitiweb.mapper;
import com.imooc.activitiweb.pojo.UserInfoBean;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;
@Mapper
@Component
public interface UserInfoBeanMapper {
/**
* 从数据库中查询用户
* @param username
* @return
*/
@Select("select * from user where username = #{username}")
UserInfoBean selectByUsername(@Param("username") String username);
}
package com.imooc.activitiweb.pojo;
public class Act_ru_task {
private String NAME_;
private String TASK_DEF_KEY_;
public String getNAME_() {
return NAME_;
}
public void setNAME_(String NAME_) {
this.NAME_ = NAME_;
}
public String getTASK_DEF_KEY_() {
return TASK_DEF_KEY_;
}
public void setTASK_DEF_KEY_(String TASK_DEF_KEY_) {
this.TASK_DEF_KEY_ = TASK_DEF_KEY_;
}
@Override
public String toString() {
return "act_ru_task{" +
"NAME_='" + NAME_ + '\'' +
", TASK_DEF_KEY_='" + TASK_DEF_KEY_ + '\'' +
'}';
}
}
package com.imooc.activitiweb.pojo;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
@Component
public class UserInfoBean implements UserDetails {
private Long id;
public String name;
private String address;
private String username;
private String password;
private String roles;
/**
* 从数据库中取出roles字符串后,进行分解,构成一个GrantedAuthority的List返回
* @return
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.stream(roles.split(",")).map(e->new SimpleGrantedAuthority(e)).collect(Collectors.toSet());
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public String getAddress() {
return address;
}
}
package com.imooc.activitiweb.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private LoginSuccessHandler loginSuccessHandler;
@Autowired
private LoginFailureHandler loginFailureHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
//----------------自定义方法登录----------------------
/* http
.formLogin()
.loginPage("/authentication/require")//这个页面必须要放在resources/resources里,否则提交不会生效,估计是安全框架的机制
.loginProcessingUrl("/authentication/require")//这里的名字和登录页的Post内容一致,就可以调框架自带的登录
.successHandler(loginSuccessHandler)
.failureHandler(loginFailureHandler)
//.defaultSuccessUrl("/hello")
//.successForwardUrl("success.html")
//.failureForwardUrl("failure.html")
.and()
.authorizeRequests()
.antMatchers("/authentication/require", "/demo-login.html", "/demo-login1.html", "/demo-login").permitAll()
.anyRequest()
.authenticated()
.and()
.headers().frameOptions().disable()//让frame页面可以正常使用
.and()
.csrf().disable();*/
//--------------------------网页登录-----------------------------
/* http
.formLogin()
.loginPage("/demo-login.html")//这个页面必须要放在resources/resources里,否则提交不会生效,估计是安全框架的机制
.loginProcessingUrl("/demo-login")//这里的名字和登录页的Post内容一致,就可以调框架自带的登录
//.defaultSuccessUrl("/hello")
//.successForwardUrl("success.html")
//.failureForwardUrl("failure.html")
.and()
.authorizeRequests()
.antMatchers("/demo-login.html", "/demo-login").permitAll()
.anyRequest()
.authenticated()
.and()
.csrf().disable();
*/
//--------------------------验证都关闭-----------------------------
//http.authorizeRequests().anyRequest().permitAll().and().logout().permitAll().and().csrf().disable().headers().frameOptions().disable();//全部页面不验证
//--------------------------activiti与layui的自定义登录-----------------------------
http
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.successHandler(loginSuccessHandler)
.failureHandler(loginFailureHandler)
//.defaultSuccessUrl("/hello")
//.successForwardUrl("success.html")
//.failureForwardUrl("failure.html")
.and()
.authorizeRequests()
.antMatchers("/login", "/demo-login.html", "/demo-login1.html", "/layuimini/page/login-1.html").permitAll()
.anyRequest()
.permitAll().and().logout().permitAll().and().csrf().disable().headers().frameOptions().disable();//全部页面不验证
}
}
package com.imooc.activitiweb.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
public class BrowserSecurityController {
private Logger logger = LoggerFactory.getLogger(getClass());
private RequestCache requestCache = new HttpSessionRequestCache();
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
//估计是在springSecurity登录验证之后,对未登录用户跳转行为进行的判断。
@RequestMapping("/login")
@ResponseStatus(code = HttpStatus.UNAUTHORIZED)
public SimpleResponse requireAuthentication(HttpServletRequest request, HttpServletResponse response) {
/*SavedRequest savedRequest = requestCache.getRequest(request,response);
if(savedRequest != null){
String targetUrl = savedRequest.getRedirectUrl();
logger.info("引发跳转的请求是:"+targetUrl);
if(StringUtils.endsWithIgnoreCase(targetUrl,".html")){
try {
redirectStrategy.sendRedirect(request, response, "/demo-login.html");
}
catch(Exception e)
{
}
}
}*/
return new SimpleResponse("需要登录,使用/demo-login.html或发起post求情");
}
}
package com.imooc.activitiweb.security;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.activitiweb.util.AjaxResponse;
import com.imooc.activitiweb.util.GlobalConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component("loginFailureHandler")
public class LoginFailureHandler implements AuthenticationFailureHandler{
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
logger.info("登录失败");
httpServletResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.getWriter().write(objectMapper.writeValueAsString(
AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
GlobalConfig.ResponseCode.ERROR.getDesc(),
"登录失败:"+e.getMessage()
)));
}
}
package com.imooc.activitiweb.security;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.activitiweb.util.AjaxResponse;
import com.imooc.activitiweb.util.GlobalConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component("loginSuccessHandler")
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
logger.info("登录成功1");
}
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
logger.info("登录成功2");
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.getWriter().write(objectMapper.writeValueAsString(
AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
GlobalConfig.ResponseCode.SUCCESS.getDesc(),
authentication.getName()
)));
}
}
package com.imooc.activitiweb.security;
import com.imooc.activitiweb.pojo.UserInfoBean;
import com.imooc.activitiweb.mapper.UserInfoBeanMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class MyUserDetailsService implements UserDetailsService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
UserInfoBeanMapper mapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//-------------------------读取数据库判断登录-----------------------
/* SysUser sysUser = sysUserService.queryByUsername(username);
if (Objects.nonNull(sysUser)) {
return User.withUsername(username).password(sysUser.getEncodePassword())
.authorities(AuthorityUtils.NO_AUTHORITIES)
.build();
}
throw new UsernameNotFoundException("username: " + username + " notfound");*/
//------------------------根据code写死用户登录------------------------------
/*
//-----------------------正常的代码-----------------
logger.info("登录用户名:" + username);
String passWord=passwordEncoder().encode("111");
logger.info("密码:" + passWord);
return new User(username,passWord, AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ACTIVITI_USER"));
//-----------------------正常的代码-----------------
*/
//页面默认会对密码加密,数据库里如果在用户注册时,用的是加密过的密码,则直接读取比较即可
//return new User(username,"$2a$10$YFZDTqyBqwHkV/vTxKrhtuyIQCMD/joeIylCs8wbvXnhOYRgD/kDq", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
//-------------------根据自定义用户属性登录-----------------------------
UserInfoBean userInfoBean = mapper.selectByUsername(username);
if (userInfoBean == null) {
throw new UsernameNotFoundException("数据库中无此用户!");
}
return userInfoBean;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
\ No newline at end of file
package com.imooc.activitiweb.security;
public class SimpleResponse {
public Object getContent() {
return content;
}
public void setContent(Object content) {
this.content = content;
}
public SimpleResponse(Object content) {
this.content = content;
}
private Object content;
}
package com.imooc.activitiweb.security;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(Predicates.or(RequestHandlerSelectors.basePackage("com.imooc.activitiweb")))
.paths(PathSelectors.any())
.build();
}
}
package com.imooc.activitiweb.util;
public class AjaxResponse {
private Integer status;
private String msg;
private Object obj;
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
private AjaxResponse(Integer status, String msg, Object obj) {
this.status = status;
this.msg = msg;
this.obj = obj;
}
public static AjaxResponse AjaxData(Integer status, String msg, Object obj) {
return new AjaxResponse(status, msg, obj);
}
}
package com.imooc.activitiweb.util;
public class GlobalConfig {
/**
* 测试场景
*/
public static final Boolean Test = false;
//windows路径
public static final String BPMN_PathMapping = "file:D:\\WangJianIDEA_Test\\activiti-imooc\\src\\main\\resources\\resources\\bpmn\\";
//Liunx路径
//public static final String BPMN_PathMapping = "file:/root/Activiti/";
public enum ResponseCode {
SUCCESS(0, "成功"),
ERROR(1, "错误");
private final int code;
private final String desc;
ResponseCode(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
}
package com.imooc.activitiweb.util;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class PathMapping implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//String[] resourceLocation = new String[]{"file:D:\\WangJianIDEA_Test\\activiti-imooc\\src\\main\\resources\\resources\\bpmn\\","classpath:/resources/"};
registry.addResourceHandler("/**").addResourceLocations("classpath:/resources/");//默认也有这个路径映射
registry.addResourceHandler("/bpmn/**").addResourceLocations(GlobalConfig.BPMN_PathMapping);
}
}
server:
port: 8080
servlet:
context-path: /
spring:
datasource:
username: root
password: YourPassWord_NiDeMiMa
url: jdbc:mysql://127.0.0.1:3306/activiti?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC&nullCatalogMeansCurrent=true
driver-class-name: com.mysql.cj.jdbc.Driver
#日志的相关配置
logging:
level:
root: info
#日志的相关配置
spring.activiti.history-level: full
spring.activiti.db-history-used: true
# spring-activiti
# 自动部署验证设置:true-开启(默认)、false-关闭
spring.activiti.check-process-definitions: false
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<springProperty scope="context" name="logHome" source="logging.home" defaultValue="logs"/>
<property name="LOG_HOME" value="c:/logs"></property>
<springProperty scope="context" name="logName" source="logging.name" defaultValue="app"/>
<property name="LOG_NAME" value="logs"></property>
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<property name="FILE_LOG_PATTERN"
value="${FILE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{HH:mm:ss.SSS}) %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
${CONSOLE_LOG_PATTERN}
</pattern>
</layout>
</appender>
<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>ERROR</level>-->
<!--<onMatch>DENY</onMatch>-->
<!--<onMismatch>ACCEPT</onMismatch>-->
<!--</filter>-->
<encoder>
<pattern>
${FILE_LOG_PATTERN}
</pattern>
</encoder>
<file>${LOG_HOME}/${LOG_NAME}-all.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>
${LOG_HOME}/backup/${LOG_NAME}-log-all-%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<maxHistory>365</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>5MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>
${FILE_LOG_PATTERN}
</pattern>
</encoder>
<file>${LOG_HOME}/${LOG_NAME}-error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>
${LOG_HOME}/backup/${LOG_NAME}-log-error-%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<maxHistory>365</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>5MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<root level="${logging.level.root}">
<appender-ref ref="consoleLog"/>
<appender-ref ref="fileInfoLog"/>
<appender-ref ref="fileErrorLog"/>
</root>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/testm1587888989443" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1587888989443" name="" targetNamespace="http://www.activiti.org/testm1587888989443" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="myDocPushProcess" isClosed="false" isExecutable="true" name="NameQingJia" processType="None">
<startEvent id="_2" name="StartEvent"/>
<endEvent id="_3" name="EndEvent"/>
<userTask activiti:assignee="bajie" activiti:exclusive="true" id="_4" name="请假申请"/>
<userTask activiti:assignee="wukong" activiti:exclusive="true" id="_5" name="请假审批"/>
<sequenceFlow id="_6" sourceRef="_2" targetRef="_4"/>
<sequenceFlow id="_7" sourceRef="_4" targetRef="_5"/>
<sequenceFlow id="_8" sourceRef="_5" targetRef="_3"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="myDocPushProcess">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<dc:Bounds height="32.0" width="32.0" x="200.0" y="40.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
<dc:Bounds height="32.0" width="32.0" x="260.0" y="350.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
<dc:Bounds height="55.0" width="85.0" x="190.0" y="140.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
<dc:Bounds height="55.0" width="85.0" x="195.0" y="260.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_4">
<di:waypoint x="216.0" y="72.0"/>
<di:waypoint x="216.0" y="140.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_4" targetElement="_5">
<di:waypoint x="235.0" y="195.0"/>
<di:waypoint x="235.0" y="260.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_5" targetElement="_3">
<di:waypoint x="270.0" y="315.0"/>
<di:waypoint x="270.0" y="351.16760302580866"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
node_modules/
tmp/
\ No newline at end of file
package-lock=false
\ No newline at end of file
var path = require('path');
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
/**
* Resolve external project resource as file path
*/
function resolvePath(project, file) {
return path.join(path.dirname(require.resolve(project)), file);
}
grunt.initConfig({
browserify: {
options: {
browserifyOptions: {
debug: true
},
transform: [
[ 'stringify', {
extensions: [ '.bpmn' ]
} ]
],
plugin: [
'esmify'
]
},
watch: {
options: {
watch: true
},
files: {
'dist/index.js': [ 'app/**/*.js' ]
}
},
app: {
files: {
'dist/index.js': [ 'app/**/*.js' ]
}
}
},
copy: {
diagram_js: {
files: [
{
src: resolvePath('diagram-js', 'assets/diagram-js.css'),
dest: 'dist/css/diagram-js.css'
}
]
},
bpmn_js: {
files: [
{
expand: true,
cwd: resolvePath('bpmn-js', 'dist/assets'),
src: ['**/*.*', '!**/*.js'],
dest: 'dist/vendor'
}
]
},
app: {
files: [
{
expand: true,
cwd: 'app/',
src: ['**/*.*', '!**/*.js'],
dest: 'dist'
}
]
}
},
less: {
options: {
dumpLineNumbers: 'comments',
paths: [
'node_modules'
]
},
styles: {
files: {
'dist/css/app.css': 'styles/app.less'
}
}
},
watch: {
options: {
livereload: true
},
samples: {
files: [ 'app/**/*.*' ],
tasks: [ 'copy:app' ]
},
less: {
files: [
'styles/**/*.less',
'node_modules/bpmn-js-properties-panel/styles/**/*.less'
],
tasks: [
'less'
]
},
},
connect: {
livereload: {
options: {
port: 9013,
livereload: true,
hostname: 'localhost',
open: true,
base: [
'dist'
]
}
}
}
});
// tasks
grunt.registerTask('build', [ 'copy', 'less', 'browserify:app' ]);
grunt.registerTask('auto-build', [
'copy',
'less',
'browserify:watch',
'connect:livereload',
'watch'
]);
grunt.registerTask('default', [ 'build' ]);
};
# bpmn-js Modeler + Properties Panel Example
This example uses [bpmn-js](https://github.com/bpmn-io/bpmn-js) and [bpmn-js-properties-panel](https://github.com/bpmn-io/bpmn-js-properties-panel). It implements a BPMN 2.0 modeler that allows you to edit execution related properties via a properties panel.
## About
This example is a node-style web application that builds a user interface around the bpmn-js BPMN 2.0 modeler.
![demo application screenshot](https://raw.githubusercontent.com/bpmn-io/bpmn-js-examples/master/properties-panel/docs/screenshot.png "Screenshot of the modeler + properties panel example")
## Usage
Add the [properties panel](https://github.com/bpmn-io/bpmn-js-properties-panel) to your project:
```
npm install --save bpmn-js-properties-panel
```
Additionally, if you'd like to use [Camunda BPM](https://camunda.org) execution related properties, include the [camunda-bpmn-moddle](https://github.com/camunda/camunda-bpmn-moddle) dependency which tells the modeler about `camunda:XXX` extension properties:
```
npm install --save camunda-bpmn-moddle
```
Now extend the [bpmn-js](https://github.com/bpmn-io/bpmn-js) modeler with two properties panel related modules, the panel itself and a provider module that controls which properties are visible for each element. Additionally you must pass an element via `propertiesPanel.parent` into which the properties panel will be rendered (cf. [`app/index.js`](https://github.com/bpmn-io/bpmn-js-examples/blob/master/properties-panel/app/index.js#L16) for details).
```javascript
var propertiesPanelModule = require('bpmn-js-properties-panel'),
// providing camunda executable properties, too
propertiesProviderModule = require('bpmn-js-properties-panel/lib/provider/camunda'),
camundaModdleDescriptor = require('camunda-bpmn-moddle/resources/camunda');
var bpmnModeler = new BpmnModeler({
container: '#js-canvas',
propertiesPanel: {
parent: '#js-properties-panel'
},
additionalModules: [
propertiesPanelModule,
propertiesProviderModule
],
// needed if you'd like to maintain camunda:XXX properties in the properties panel
moddleExtensions: {
camunda: camundaModdleDescriptor
}
});
```
## Building the Example
You need a [NodeJS](http://nodejs.org) development stack with [npm](https://npmjs.org) and installed to build the project.
To install all project dependencies execute
```
npm install
```
Build the example using [browserify](http://browserify.org) via
```
npm run all
```
You may also spawn a development setup by executing
```
npm run dev
```
Both tasks generate the distribution ready client-side modeler application into the `dist` folder.
Serve the application locally or via a web server (nginx, apache, embedded).
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8" />
<title>在线绘制流程</title>
<link rel="icon" href="favicon.ico">
<link rel="stylesheet" href="css/diagram-js.css" />
<link rel="stylesheet" href="vendor/bpmn-font/css/bpmn-embedded.css" />
<link rel="stylesheet" href="css/app.css" />
<style>
.item{
display: none;
}
.bjs-powered-by {
display: none;
}
.buttons > li {
/* display: inline-block; */
margin-right: 10px;
height: 26px;
line-height: 26px;
float: left;
}
.buttons > li > a.btn {
background: #00BCD4;
border: none;
outline: none;
padding: 0px 10px;
color: #fff;
display: inline-block;
opacity: 1;
height: 26px;
font-size: 14px;
line-height: 26px;
}
.label {
background: #00BCD4;
border: none;
outline: none;
padding: 0px 10px;
color: #fff;
display: inline-block;
cursor: pointer;
opacity: 1;
height: 26px;
font-size: 14px;
line-height: 26px;
}
.sy-mask{width:100%;
height:100%;
position:fixed;
background:rgba(0,0,0,0.8);
left:0;top:0;z-index:1000;
display: none;
}
.sy-alert{
position:fixed;display:none;background:#fff;border-radius:5px;overflow:hidden;width:300px;max-width:90%;max-height:80%;left:0;right:0;margin:0 auto;z-index:9999}.sy-alert.animated{-webkit-animation-duration:.3s;animation-duration:.3s}.sy-alert .sy-title{height:45px;color:#333;line-height:45px;font-size:15px;border-bottom:1px solid #eee;padding:0 12px}.sy-alert .sy-content{padding:20px;text-align:center;font-size:14px;line-height:24px;color:#666;overflow-y:auto}.sy-alert .sy-btn{height:50%;border-top:1px solid #eee;overflow:hidden}.sy-alert .sy-btn button{float:left;border:0;color:#333;cursor:pointer;background:#fff;width:50%;line-height:45px;font-size:15px;text-align:center}.sy-alert .sy-btn button:nth-child(1){color:#888;border-right:1px solid #eee}.sy-alert.sy-alert-alert .sy-btn button{float:none;width:100%}.sy-alert.sy-alert-tips{text-align:center;width:150px;background:rgba(0,0,0,0.7)}.sy-alert.sy-alert-tips .sy-content{padding:8px;color:#fff;font-size:14px}.sy-alert.sy-alert-model .sy-content{text-align:left}.sy-alert.sy-alert-model .sy-content .form .input-item{margin-bottom:12px;position:relative}.sy-alert.sy-alert-model .sy-content .form .input-item input{display:block;position:relative;width:100%;border:1px solid #eee;padding:10px}.sy-alert.sy-alert-model .sy-content .form .input-item .getcode{border:0;top:0;right:0;position:absolute;background:0;line-height:37px;color:#f60;width:100px;text-align:center}
</style>
</head>
<body>
<div class="content with-diagram" id="js-drop-zone">
<div class="message error">
<div class="note">
<p>无法显示bpms2.0</p>
<div class="details">
<span>错误详细信息</span>
<pre></pre>
</div>
</div>
</div>
<div class="canvas" id="js-canvas"></div>
<div class="properties-panel-parent" id="js-properties-panel"></div>
</div>
<ul class="buttons">
<li class="item upload">
<form id="form1" name="myForm" onsubmit="return false" method="post" enctype="multipart/form-data" title="上传文件">
<input type="file" name="uploadFile" id="uploadFile" accept=".bpmn" style="display: none">
<label class="label" for="uploadFile" >打开</label>
</form>
</li>
<li class="item submit">
<a class="btn" id="js-download-diagram">
提交
</a>
</li>
<li class="item download">
<a class="btn" href id="saveBpmn">下载</a>
</li>
</ul>
<div class="sy-alert sy-alert-model animated" sy-enter="zoomIn" sy-leave="zoomOut" sy-type="confirm" sy-mask="true" id="alert" >
<div class="sy-title">新增流程</div>
<div class="sy-content">
<div class="form">
<p class="input-item"><input id="deploymentName" type="text" placeholder="请输入流程名称"></p>
</div>
</div>
<div class="sy-btn">
<button class="cancel" >取消</button>
<button id="sure">确定</button>
</div>
</div>
<div class="sy-mask cancel"></div>
<script src="index.js"></script>
</body>
</html>
\ No newline at end of file
import $ from 'jquery';
import BpmnModeler from 'bpmn-js/lib/Modeler';
//import propertiesPanelModule from '../resources/properties-panel';
import propertiesPanelModule from 'bpmn-js-properties-panel';
import propertiesProviderModule from '../resources/properties-panel/provider/activiti';
import activitiModdleDescriptor from '../resources/activiti.json';
import customTranslate from '../resources/customTranslate/customTranslate';
import customControlsModule from '../resources/customControls';
import tools from '../resources/tools'
import diagramXML from '../resources/newDiagram.bpmn';
const proHost = window.location.protocol + "//" + window.location.host;
const href = window.location.href.split("bpmnjs")[0];
const key = href.split(window.location.host)[1];
const publicurl = proHost + key;
// 添加翻译组件
var customTranslateModule = {
translate: ['value', customTranslate]
};
var ColorJson = [{
'name': 'test1',
'stroke': 'green',
'fill': 'yellow'
}, {
'name': 'test2',
'stroke': 'blue',
'fill': 'red'
}]
var container = $('#js-drop-zone');
var canvas = $('#js-canvas');
var bpmnModeler = new BpmnModeler({
container: canvas,
propertiesPanel: {
parent: '#js-properties-panel'
},
additionalModules: [
propertiesPanelModule,
propertiesProviderModule,
customControlsModule,
customTranslateModule
],
moddleExtensions: {
activiti:activitiModdleDescriptor
}
});
container.removeClass('with-diagram');
// 判断浏览器支持程度
if (!window.FileList || !window.FileReader) {
window.alert('请使用谷歌、火狐、IE10+浏览器');
} else {
tools.registerFileDrop(container, tools.createDiagram(diagramXML, bpmnModeler, container));
}
$(function () {
// 创建bpmn
var param = tools.getUrlParam(window.location.href)
$('.item').show()
if (param.type === 'addBpmn') {
tools.createDiagram(diagramXML, bpmnModeler, container);
} else if (param.type === 'lookBpmn') { //编辑bpmn
$('.item').hide()
$('.download').show()
const Id = param.deploymentFileUUID || '6d4af2dc-bab0-11ea-b584-3cf011eaafca'
const Name=param.deploymentName || 'String.bpmn'
//加载后台方法获取xml
var param={
"deploymentId":Id,
"resourceName":Name
}
$.ajax({
url: publicurl+'processDefinition/getDefinitionXML',
type: 'GET',
data: param,
dataType:'text',
success: function (result) {
var newXmlData = result
tools.createDiagram(newXmlData, bpmnModeler, container);
setTimeout(function () {
for (var i in ColorJson) {
tools.setColor(ColorJson[i],bpmnModeler)
}
}, 200)
},
error: function (err) {
console.log(err)
}
});
}
// 点击新增
$('#js-download-diagram').on("click", function () {
tools.syopen('alert')
})
// 点击取消
$('.cancel').on("click",function () {
tools.syhide('alert')
})
// 点击确定
$('#sure').on('click',function(){
const text=$("#deploymentName").val()
tools.saveBpmn(bpmnModeler,text)
})
// 点击下载
$("#saveBpmn").on("click", function () {
tools.downLoad(bpmnModeler)
})
// 点击上传
$("#uploadFile").on("change", function () {
tools.upload(bpmnModeler,container)
})
});
此差异已折叠。
/**
* outline styles
*/
.djs-outline {
fill: none;
visibility: hidden;
}
.djs-element.hover .djs-outline,
.djs-element.selected .djs-outline {
visibility: visible;
shape-rendering: crispEdges;
stroke-dasharray: 3,3;
}
.djs-element.selected .djs-outline {
stroke: #8888FF;
stroke-width: 1px;
}
.djs-element.hover .djs-outline {
stroke: #FF8888;
stroke-width: 1px;
}
.djs-shape.connect-ok .djs-visual > :nth-child(1) {
fill: #DCFECC /* light-green */ !important;
}
.djs-shape.connect-not-ok .djs-visual > :nth-child(1),
.djs-shape.drop-not-ok .djs-visual > :nth-child(1) {
fill: #f9dee5 /* light-red */ !important;
}
.djs-shape.new-parent .djs-visual > :nth-child(1) {
fill: #F7F9FF !important;
}
svg.drop-not-ok {
background: #f9dee5 /* light-red */ !important;
}
svg.new-parent {
background: #F7F9FF /* light-blue */ !important;
}
.djs-connection.connect-ok .djs-visual > :nth-child(1),
.djs-connection.drop-ok .djs-visual > :nth-child(1) {
stroke: #90DD5F /* light-green */ !important;
}
.djs-connection.connect-not-ok .djs-visual > :nth-child(1),
.djs-connection.drop-not-ok .djs-visual > :nth-child(1) {
stroke: #E56283 /* light-red */ !important;
}
.drop-not-ok,
.connect-not-ok {
cursor: not-allowed;
}
.djs-element.attach-ok .djs-visual > :nth-child(1) {
stroke-width: 5px !important;
stroke: rgba(255, 116, 0, 0.7) !important;
}
.djs-frame.connect-not-ok .djs-visual > :nth-child(1),
.djs-frame.drop-not-ok .djs-visual > :nth-child(1) {
stroke-width: 3px !important;
stroke: #E56283 /* light-red */ !important;
fill: none !important;
}
/**
* Selection box style
*
*/
.djs-lasso-overlay {
fill: rgb(255, 116, 0);
fill-opacity: 0.1;
stroke-dasharray: 5 1 3 1;
stroke: rgb(255, 116, 0);
shape-rendering: crispEdges;
pointer-events: none;
}
/**
* Resize styles
*/
.djs-resize-overlay {
fill: none;
stroke-dasharray: 5 1 3 1;
stroke: rgb(255, 116, 0);
pointer-events: none;
}
.djs-resizer-hit {
fill: none;
pointer-events: all;
}
.djs-resizer-visual {
fill: white;
stroke-width: 1px;
stroke: black;
shape-rendering: crispEdges;
stroke-opacity: 0.2;
}
.djs-cursor-resize-nwse,
.djs-resizer-nw,
.djs-resizer-se {
cursor: nwse-resize;
}
.djs-cursor-resize-nesw,
.djs-resizer-ne,
.djs-resizer-sw {
cursor: nesw-resize;
}
.djs-shape.djs-resizing > .djs-outline {
visibility: hidden !important;
}
.djs-shape.djs-resizing > .djs-resizer {
visibility: hidden;
}
.djs-dragger > .djs-resizer {
visibility: hidden;
}
/**
* drag styles
*/
.djs-dragger * {
fill: none !important;
stroke: rgb(255, 116, 0) !important;
}
.djs-dragger tspan,
.djs-dragger text {
fill: rgb(255, 116, 0) !important;
stroke: none !important;
}
marker.djs-dragger circle,
marker.djs-dragger path,
marker.djs-dragger polygon,
marker.djs-dragger polyline,
marker.djs-dragger rect {
fill: rgb(255, 116, 0) !important;
stroke: none !important;
}
marker.djs-dragger text,
marker.djs-dragger tspan {
fill: none !important;
stroke: rgb(255, 116, 0) !important;
}
.djs-dragging {
opacity: 0.3;
}
.djs-dragging,
.djs-dragging > * {
pointer-events: none !important;
}
.djs-dragging .djs-context-pad,
.djs-dragging .djs-outline {
display: none !important;
}
/**
* no pointer events for visual
*/
.djs-visual,
.djs-outline {
pointer-events: none;
}
.djs-element.attach-ok .djs-hit {
stroke-width: 60px !important;
}
/**
* all pointer events for hit shape
*/
.djs-element > .djs-hit-all {
pointer-events: all;
}
.djs-element > .djs-hit-stroke,
.djs-element > .djs-hit-click-stroke {
pointer-events: stroke;
}
/**
* all pointer events for hit shape
*/
.djs-drag-active .djs-element > .djs-hit-click-stroke {
pointer-events: all;
}
/**
* shape / connection basic styles
*/
.djs-connection .djs-visual {
stroke-width: 2px;
fill: none;
}
.djs-cursor-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}
.djs-cursor-grabbing {
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}
.djs-cursor-crosshair {
cursor: crosshair;
}
.djs-cursor-move {
cursor: move;
}
.djs-cursor-resize-ns {
cursor: ns-resize;
}
.djs-cursor-resize-ew {
cursor: ew-resize;
}
/**
* snapping
*/
.djs-snap-line {
stroke: rgb(255, 195, 66);
stroke: rgba(255, 195, 66, 0.50);
stroke-linecap: round;
stroke-width: 2px;
pointer-events: none;
}
/**
* snapping
*/
.djs-crosshair {
stroke: #555;
stroke-linecap: round;
stroke-width: 1px;
pointer-events: none;
shape-rendering: crispEdges;
stroke-dasharray: 5, 5;
}
/**
* palette
*/
.djs-palette {
position: absolute;
left: 20px;
top: 20px;
box-sizing: border-box;
width: 48px;
}
.djs-palette .separator {
margin: 0 5px;
padding-top: 5px;
border: none;
border-bottom: solid 1px #DDD;
clear: both;
}
.djs-palette .entry:before {
vertical-align: text-bottom;
}
.djs-palette .djs-palette-toggle {
cursor: pointer;
}
.djs-palette .entry,
.djs-palette .djs-palette-toggle {
color: #333;
font-size: 30px;
text-align: center;
}
.djs-palette .entry {
float: left;
}
.djs-palette .entry img {
max-width: 100%;
}
.djs-palette .djs-palette-entries:after {
content: '';
display: table;
clear: both;
}
.djs-palette .djs-palette-toggle:hover {
background: #666;
}
.djs-palette .entry:hover {
color: rgb(255, 116, 0);
}
.djs-palette .highlighted-entry {
color: rgb(255, 116, 0) !important;
}
.djs-palette .entry,
.djs-palette .djs-palette-toggle {
width: 46px;
height: 46px;
line-height: 46px;
cursor: default;
}
/**
* Palette open / two-column layout is controlled via
* classes on the palette. Events to hook into palette
* changed life-cycle are available in addition.
*/
.djs-palette.two-column.open {
width: 94px;
}
.djs-palette:not(.open) .djs-palette-entries {
display: none;
}
.djs-palette:not(.open) {
overflow: hidden;
}
.djs-palette.open .djs-palette-toggle {
display: none;
}
/**
* context-pad
*/
.djs-overlay-context-pad {
width: 72px;
}
.djs-context-pad {
position: absolute;
display: none;
pointer-events: none;
}
.djs-context-pad .entry {
width: 22px;
height: 22px;
text-align: center;
display: inline-block;
font-size: 22px;
margin: 0 2px 2px 0;
border-radius: 3px;
cursor: default;
background-color: #FEFEFE;
box-shadow: 0 0 2px 1px #FEFEFE;
pointer-events: all;
}
.djs-context-pad .entry:before {
vertical-align: top;
}
.djs-context-pad .entry:hover {
background: rgb(255, 252, 176);
}
.djs-context-pad.open {
display: block;
}
/**
* popup styles
*/
.djs-popup .entry {
line-height: 20px;
white-space: nowrap;
cursor: default;
}
/* larger font for prefixed icons */
.djs-popup .entry:before {
vertical-align: middle;
font-size: 20px;
}
.djs-popup .entry > span {
vertical-align: middle;
font-size: 14px;
}
.djs-popup .entry:hover,
.djs-popup .entry.active:hover {
background: rgb(255, 252, 176);
}
.djs-popup .entry.disabled {
background: inherit;
}
.djs-popup .djs-popup-header .entry {
display: inline-block;
padding: 2px 3px 2px 3px;
border: solid 1px transparent;
border-radius: 3px;
}
.djs-popup .djs-popup-header .entry.active {
color: rgb(255, 116, 0);
border: solid 1px rgb(255, 116, 0);
background-color: #F6F6F6;
}
.djs-popup-body .entry {
padding: 4px 10px 4px 5px;
}
.djs-popup-body .entry > span {
margin-left: 5px;
}
.djs-popup-body {
background-color: #FEFEFE;
}
.djs-popup-header {
border-bottom: 1px solid #DDD;
}
.djs-popup-header .entry {
margin: 1px;
margin-left: 3px;
}
.djs-popup-header .entry:last-child {
margin-right: 3px;
}
/**
* popup / palette styles
*/
.djs-popup, .djs-palette {
background: #FAFAFA;
border: solid 1px #CCC;
border-radius: 2px;
}
/**
* touch
*/
.djs-shape,
.djs-connection {
touch-action: none;
}
.djs-segment-dragger,
.djs-bendpoint {
display: none;
}
/**
* bendpoints
*/
.djs-segment-dragger .djs-visual {
fill: rgba(255, 255, 121, 0.2);
stroke-width: 1px;
stroke-opacity: 1;
stroke: rgba(255, 255, 121, 0.3);
}
.djs-bendpoint .djs-visual {
fill: rgba(255, 255, 121, 0.8);
stroke-width: 1px;
stroke-opacity: 0.5;
stroke: black;
}
.djs-segment-dragger:hover,
.djs-bendpoints.hover .djs-segment-dragger,
.djs-bendpoints.selected .djs-segment-dragger,
.djs-bendpoint:hover,
.djs-bendpoints.hover .djs-bendpoint,
.djs-bendpoints.selected .djs-bendpoint {
display: block;
}
.djs-drag-active .djs-bendpoints * {
display: none;
}
.djs-bendpoints:not(.hover) .floating {
display: none;
}
.djs-segment-dragger:hover .djs-visual,
.djs-segment-dragger.djs-dragging .djs-visual,
.djs-bendpoint:hover .djs-visual,
.djs-bendpoint.floating .djs-visual {
fill: yellow;
stroke-opacity: 0.5;
stroke: black;
}
.djs-bendpoint.floating .djs-hit {
pointer-events: none;
}
.djs-segment-dragger .djs-hit,
.djs-bendpoint .djs-hit {
pointer-events: all;
fill: none;
}
.djs-segment-dragger.horizontal .djs-hit {
cursor: ns-resize;
}
.djs-segment-dragger.vertical .djs-hit {
cursor: ew-resize;
}
.djs-segment-dragger.djs-dragging .djs-hit {
pointer-events: none;
}
.djs-updating,
.djs-updating > * {
pointer-events: none !important;
}
.djs-updating .djs-context-pad,
.djs-updating .djs-outline,
.djs-updating .djs-bendpoint,
.connect-ok .djs-bendpoint,
.connect-not-ok .djs-bendpoint,
.drop-ok .djs-bendpoint,
.drop-not-ok .djs-bendpoint {
display: none !important;
}
.djs-segment-dragger.djs-dragging,
.djs-bendpoint.djs-dragging {
display: block;
opacity: 1.0;
}
.djs-segment-dragger.djs-dragging .djs-visual,
.djs-bendpoint.djs-dragging .djs-visual {
fill: yellow;
stroke-opacity: 0.5;
}
/**
* tooltips
*/
.djs-tooltip-error {
font-size: 11px;
line-height: 18px;
text-align: left;
padding: 5px;
opacity: 0.7;
}
.djs-tooltip-error > * {
width: 160px;
background: rgb(252, 236, 240);
color: rgb(158, 76, 76);
padding: 3px 7px;
border-radius: 5px;
border-left: solid 5px rgb(174, 73, 73);
}
.djs-tooltip-error:hover {
opacity: 1;
}
/**
* search pad
*/
.djs-search-container {
position: absolute;
top: 20px;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
width: 25%;
min-width: 300px;
max-width: 400px;
z-index: 10;
font-size: 1.05em;
opacity: 0.9;
background: #FAFAFA;
border: solid 1px #CCC;
border-radius: 2px;
}
.djs-search-container:not(.open) {
display: none;
}
.djs-search-input input {
font-size: 1.05em;
width: 100%;
padding: 6px 10px;
border: 1px solid #ccc;
}
.djs-search-input input:focus {
outline: none;
border-color: #52B415;
}
.djs-search-results {
position: relative;
overflow-y: auto;
max-height: 200px;
}
.djs-search-results:hover {
/*background: #fffdd7;*/
cursor: pointer;
}
.djs-search-result {
width: 100%;
padding: 6px 10px;
background: white;
border-bottom: solid 1px #AAA;
border-radius: 1px;
}
.djs-search-highlight {
color: black;
}
.djs-search-result-primary {
margin: 0 0 10px;
}
.djs-search-result-secondary {
font-family: monospace;
margin: 0;
}
.djs-search-result:hover {
background: #fdffd6;
}
.djs-search-result-selected {
background: #fffcb0;
}
.djs-search-result-selected:hover {
background: #f7f388;
}
.djs-search-overlay {
background: yellow;
opacity: 0.3;
}
/**
* hidden styles
*/
.djs-element-hidden,
.djs-element-hidden .djs-hit,
.djs-element-hidden .djs-outline,
.djs-label-hidden .djs-label {
display: none !important;
}
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8" />
<title>在线绘制流程</title>
<link rel="icon" href="favicon.ico">
<link rel="stylesheet" href="css/diagram-js.css" />
<link rel="stylesheet" href="vendor/bpmn-font/css/bpmn-embedded.css" />
<link rel="stylesheet" href="css/app.css" />
<style>
.item{
display: none;
}
.bjs-powered-by {
display: none;
}
.buttons > li {
/* display: inline-block; */
margin-right: 10px;
height: 26px;
line-height: 26px;
float: left;
}
.buttons > li > a.btn {
background: #00BCD4;
border: none;
outline: none;
padding: 0px 10px;
color: #fff;
display: inline-block;
opacity: 1;
height: 26px;
font-size: 14px;
line-height: 26px;
}
.label {
background: #00BCD4;
border: none;
outline: none;
padding: 0px 10px;
color: #fff;
display: inline-block;
cursor: pointer;
opacity: 1;
height: 26px;
font-size: 14px;
line-height: 26px;
}
.sy-mask{width:100%;
height:100%;
position:fixed;
background:rgba(0,0,0,0.8);
left:0;top:0;z-index:1000;
display: none;
}
.sy-alert{
position:fixed;display:none;background:#fff;border-radius:5px;overflow:hidden;width:300px;max-width:90%;max-height:80%;left:0;right:0;margin:0 auto;z-index:9999}.sy-alert.animated{-webkit-animation-duration:.3s;animation-duration:.3s}.sy-alert .sy-title{height:45px;color:#333;line-height:45px;font-size:15px;border-bottom:1px solid #eee;padding:0 12px}.sy-alert .sy-content{padding:20px;text-align:center;font-size:14px;line-height:24px;color:#666;overflow-y:auto}.sy-alert .sy-btn{height:50%;border-top:1px solid #eee;overflow:hidden}.sy-alert .sy-btn button{float:left;border:0;color:#333;cursor:pointer;background:#fff;width:50%;line-height:45px;font-size:15px;text-align:center}.sy-alert .sy-btn button:nth-child(1){color:#888;border-right:1px solid #eee}.sy-alert.sy-alert-alert .sy-btn button{float:none;width:100%}.sy-alert.sy-alert-tips{text-align:center;width:150px;background:rgba(0,0,0,0.7)}.sy-alert.sy-alert-tips .sy-content{padding:8px;color:#fff;font-size:14px}.sy-alert.sy-alert-model .sy-content{text-align:left}.sy-alert.sy-alert-model .sy-content .form .input-item{margin-bottom:12px;position:relative}.sy-alert.sy-alert-model .sy-content .form .input-item input{display:block;position:relative;width:100%;border:1px solid #eee;padding:10px}.sy-alert.sy-alert-model .sy-content .form .input-item .getcode{border:0;top:0;right:0;position:absolute;background:0;line-height:37px;color:#f60;width:100px;text-align:center}
</style>
</head>
<body>
<div class="content with-diagram" id="js-drop-zone">
<div class="message error">
<div class="note">
<p>无法显示bpms2.0</p>
<div class="details">
<span>错误详细信息</span>
<pre></pre>
</div>
</div>
</div>
<div class="canvas" id="js-canvas"></div>
<div class="properties-panel-parent" id="js-properties-panel"></div>
</div>
<ul class="buttons">
<li class="item upload">
<form id="form1" name="myForm" onsubmit="return false" method="post" enctype="multipart/form-data" title="上传文件">
<input type="file" name="uploadFile" id="uploadFile" accept=".bpmn" style="display: none">
<label class="label" for="uploadFile" >打开</label>
</form>
</li>
<li class="item submit">
<a class="btn" id="js-download-diagram">
提交
</a>
</li>
<li class="item download">
<a class="btn" href id="saveBpmn">下载</a>
</li>
</ul>
<div class="sy-alert sy-alert-model animated" sy-enter="zoomIn" sy-leave="zoomOut" sy-type="confirm" sy-mask="true" id="alert" >
<div class="sy-title">新增流程</div>
<div class="sy-content">
<div class="form">
<p class="input-item"><input id="deploymentName" type="text" placeholder="请输入流程名称"></p>
</div>
</div>
<div class="sy-btn">
<button class="cancel" >取消</button>
<button id="sure">确定</button>
</div>
</div>
<div class="sy-mask cancel"></div>
<script src="index.js"></script>
</body>
</html>
\ No newline at end of file
此差异已折叠。
.bpmn-icon-screw-wrench:before { content: '\e800'; } /* '' */
.bpmn-icon-trash:before { content: '\e801'; } /* '' */
.bpmn-icon-conditional-flow:before { content: '\e802'; } /* '' */
.bpmn-icon-default-flow:before { content: '\e803'; } /* '' */
.bpmn-icon-gateway-parallel:before { content: '\e804'; } /* '' */
.bpmn-icon-intermediate-event-catch-cancel:before { content: '\e805'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-message:before { content: '\e806'; } /* '' */
.bpmn-icon-start-event-compensation:before { content: '\e807'; } /* '' */
.bpmn-icon-start-event-non-interrupting-parallel-multiple:before { content: '\e808'; } /* '' */
.bpmn-icon-loop-marker:before { content: '\e809'; } /* '' */
.bpmn-icon-parallel-mi-marker:before { content: '\e80a'; } /* '' */
.bpmn-icon-start-event-non-interrupting-signal:before { content: '\e80b'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-timer:before { content: '\e80c'; } /* '' */
.bpmn-icon-intermediate-event-catch-parallel-multiple:before { content: '\e80d'; } /* '' */
.bpmn-icon-intermediate-event-catch-compensation:before { content: '\e80e'; } /* '' */
.bpmn-icon-gateway-xor:before { content: '\e80f'; } /* '' */
.bpmn-icon-connection:before { content: '\e810'; } /* '' */
.bpmn-icon-end-event-cancel:before { content: '\e811'; } /* '' */
.bpmn-icon-intermediate-event-catch-condition:before { content: '\e812'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-parallel-multiple:before { content: '\e813'; } /* '' */
.bpmn-icon-start-event-condition:before { content: '\e814'; } /* '' */
.bpmn-icon-start-event-non-interrupting-timer:before { content: '\e815'; } /* '' */
.bpmn-icon-sequential-mi-marker:before { content: '\e816'; } /* '' */
.bpmn-icon-user-task:before { content: '\e817'; } /* '' */
.bpmn-icon-business-rule:before { content: '\e818'; } /* '' */
.bpmn-icon-sub-process-marker:before { content: '\e819'; } /* '' */
.bpmn-icon-start-event-parallel-multiple:before { content: '\e81a'; } /* '' */
.bpmn-icon-start-event-error:before { content: '\e81b'; } /* '' */
.bpmn-icon-intermediate-event-catch-signal:before { content: '\e81c'; } /* '' */
.bpmn-icon-intermediate-event-catch-error:before { content: '\e81d'; } /* '' */
.bpmn-icon-end-event-compensation:before { content: '\e81e'; } /* '' */
.bpmn-icon-subprocess-collapsed:before { content: '\e81f'; } /* '' */
.bpmn-icon-subprocess-expanded:before { content: '\e820'; } /* '' */
.bpmn-icon-task:before { content: '\e821'; } /* '' */
.bpmn-icon-end-event-error:before { content: '\e822'; } /* '' */
.bpmn-icon-intermediate-event-catch-escalation:before { content: '\e823'; } /* '' */
.bpmn-icon-intermediate-event-catch-timer:before { content: '\e824'; } /* '' */
.bpmn-icon-start-event-escalation:before { content: '\e825'; } /* '' */
.bpmn-icon-start-event-signal:before { content: '\e826'; } /* '' */
.bpmn-icon-business-rule-task:before { content: '\e827'; } /* '' */
.bpmn-icon-manual:before { content: '\e828'; } /* '' */
.bpmn-icon-receive:before { content: '\e829'; } /* '' */
.bpmn-icon-call-activity:before { content: '\e82a'; } /* '' */
.bpmn-icon-start-event-timer:before { content: '\e82b'; } /* '' */
.bpmn-icon-start-event-message:before { content: '\e82c'; } /* '' */
.bpmn-icon-intermediate-event-none:before { content: '\e82d'; } /* '' */
.bpmn-icon-intermediate-event-catch-link:before { content: '\e82e'; } /* '' */
.bpmn-icon-end-event-escalation:before { content: '\e82f'; } /* '' */
.bpmn-icon-text-annotation:before { content: '\e830'; } /* '' */
.bpmn-icon-bpmn-io:before { content: '\e831'; } /* '' */
.bpmn-icon-gateway-complex:before { content: '\e832'; } /* '' */
.bpmn-icon-gateway-eventbased:before { content: '\e833'; } /* '' */
.bpmn-icon-gateway-none:before { content: '\e834'; } /* '' */
.bpmn-icon-gateway-or:before { content: '\e835'; } /* '' */
.bpmn-icon-end-event-terminate:before { content: '\e836'; } /* '' */
.bpmn-icon-end-event-signal:before { content: '\e837'; } /* '' */
.bpmn-icon-end-event-none:before { content: '\e838'; } /* '' */
.bpmn-icon-end-event-multiple:before { content: '\e839'; } /* '' */
.bpmn-icon-end-event-message:before { content: '\e83a'; } /* '' */
.bpmn-icon-end-event-link:before { content: '\e83b'; } /* '' */
.bpmn-icon-intermediate-event-catch-message:before { content: '\e83c'; } /* '' */
.bpmn-icon-intermediate-event-throw-compensation:before { content: '\e83d'; } /* '' */
.bpmn-icon-start-event-multiple:before { content: '\e83e'; } /* '' */
.bpmn-icon-script:before { content: '\e83f'; } /* '' */
.bpmn-icon-manual-task:before { content: '\e840'; } /* '' */
.bpmn-icon-send:before { content: '\e841'; } /* '' */
.bpmn-icon-service:before { content: '\e842'; } /* '' */
.bpmn-icon-receive-task:before { content: '\e843'; } /* '' */
.bpmn-icon-user:before { content: '\e844'; } /* '' */
.bpmn-icon-start-event-none:before { content: '\e845'; } /* '' */
.bpmn-icon-intermediate-event-throw-escalation:before { content: '\e846'; } /* '' */
.bpmn-icon-intermediate-event-catch-multiple:before { content: '\e847'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-escalation:before { content: '\e848'; } /* '' */
.bpmn-icon-intermediate-event-throw-link:before { content: '\e849'; } /* '' */
.bpmn-icon-start-event-non-interrupting-condition:before { content: '\e84a'; } /* '' */
.bpmn-icon-data-object:before { content: '\e84b'; } /* '' */
.bpmn-icon-script-task:before { content: '\e84c'; } /* '' */
.bpmn-icon-send-task:before { content: '\e84d'; } /* '' */
.bpmn-icon-data-store:before { content: '\e84e'; } /* '' */
.bpmn-icon-start-event-non-interrupting-escalation:before { content: '\e84f'; } /* '' */
.bpmn-icon-intermediate-event-throw-message:before { content: '\e850'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-multiple:before { content: '\e851'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-signal:before { content: '\e852'; } /* '' */
.bpmn-icon-intermediate-event-throw-multiple:before { content: '\e853'; } /* '' */
.bpmn-icon-start-event-non-interrupting-message:before { content: '\e854'; } /* '' */
.bpmn-icon-ad-hoc-marker:before { content: '\e855'; } /* '' */
.bpmn-icon-service-task:before { content: '\e856'; } /* '' */
.bpmn-icon-task-none:before { content: '\e857'; } /* '' */
.bpmn-icon-compensation-marker:before { content: '\e858'; } /* '' */
.bpmn-icon-start-event-non-interrupting-multiple:before { content: '\e859'; } /* '' */
.bpmn-icon-intermediate-event-throw-signal:before { content: '\e85a'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-condition:before { content: '\e85b'; } /* '' */
.bpmn-icon-participant:before { content: '\e85c'; } /* '' */
.bpmn-icon-event-subprocess-expanded:before { content: '\e85d'; } /* '' */
.bpmn-icon-lane-insert-below:before { content: '\e85e'; } /* '' */
.bpmn-icon-space-tool:before { content: '\e85f'; } /* '' */
.bpmn-icon-connection-multi:before { content: '\e860'; } /* '' */
.bpmn-icon-lane:before { content: '\e861'; } /* '' */
.bpmn-icon-lasso-tool:before { content: '\e862'; } /* '' */
.bpmn-icon-lane-insert-above:before { content: '\e863'; } /* '' */
.bpmn-icon-lane-divide-three:before { content: '\e864'; } /* '' */
.bpmn-icon-lane-divide-two:before { content: '\e865'; } /* '' */
.bpmn-icon-data-input:before { content: '\e866'; } /* '' */
.bpmn-icon-data-output:before { content: '\e867'; } /* '' */
.bpmn-icon-hand-tool:before { content: '\e868'; } /* '' */
.bpmn-icon-group:before { content: '\e869'; } /* '' */
.bpmn-icon-transaction:before { content: '\e8c4'; } /* '' */
\ No newline at end of file
@font-face {
font-family: 'bpmn';
src: url('../font/bpmn.eot?26374340');
src: url('../font/bpmn.eot?26374340#iefix') format('embedded-opentype'),
url('../font/bpmn.woff2?26374340') format('woff2'),
url('../font/bpmn.woff?26374340') format('woff'),
url('../font/bpmn.ttf?26374340') format('truetype'),
url('../font/bpmn.svg?26374340#bpmn') format('svg');
font-weight: normal;
font-style: normal;
}
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
/*
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'bpmn';
src: url('../font/bpmn.svg?26374340#bpmn') format('svg');
}
}
*/
[class^="bpmn-icon-"]:before, [class*=" bpmn-icon-"]:before {
font-family: "bpmn";
font-style: normal;
font-weight: normal;
speak: never;
display: inline-block;
text-decoration: inherit;
width: 1em;
/* margin-right: .2em; */
text-align: center;
/* opacity: .8; */
/* For safety - reset parent styles, that can break glyph codes*/
font-variant: normal;
text-transform: none;
/* fix buttons height, for twitter bootstrap */
line-height: 1em;
/* Animation center compensation - margins should be symmetric */
/* remove if not needed */
/* margin-left: .2em; */
/* you can be more comfortable with increased icons size */
/* font-size: 120%; */
/* Font smoothing. That was taken from TWBS */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* Uncomment for 3D effect */
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}
.bpmn-icon-screw-wrench:before { content: '\e800'; } /* '' */
.bpmn-icon-trash:before { content: '\e801'; } /* '' */
.bpmn-icon-conditional-flow:before { content: '\e802'; } /* '' */
.bpmn-icon-default-flow:before { content: '\e803'; } /* '' */
.bpmn-icon-gateway-parallel:before { content: '\e804'; } /* '' */
.bpmn-icon-intermediate-event-catch-cancel:before { content: '\e805'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-message:before { content: '\e806'; } /* '' */
.bpmn-icon-start-event-compensation:before { content: '\e807'; } /* '' */
.bpmn-icon-start-event-non-interrupting-parallel-multiple:before { content: '\e808'; } /* '' */
.bpmn-icon-loop-marker:before { content: '\e809'; } /* '' */
.bpmn-icon-parallel-mi-marker:before { content: '\e80a'; } /* '' */
.bpmn-icon-start-event-non-interrupting-signal:before { content: '\e80b'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-timer:before { content: '\e80c'; } /* '' */
.bpmn-icon-intermediate-event-catch-parallel-multiple:before { content: '\e80d'; } /* '' */
.bpmn-icon-intermediate-event-catch-compensation:before { content: '\e80e'; } /* '' */
.bpmn-icon-gateway-xor:before { content: '\e80f'; } /* '' */
.bpmn-icon-connection:before { content: '\e810'; } /* '' */
.bpmn-icon-end-event-cancel:before { content: '\e811'; } /* '' */
.bpmn-icon-intermediate-event-catch-condition:before { content: '\e812'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-parallel-multiple:before { content: '\e813'; } /* '' */
.bpmn-icon-start-event-condition:before { content: '\e814'; } /* '' */
.bpmn-icon-start-event-non-interrupting-timer:before { content: '\e815'; } /* '' */
.bpmn-icon-sequential-mi-marker:before { content: '\e816'; } /* '' */
.bpmn-icon-user-task:before { content: '\e817'; } /* '' */
.bpmn-icon-business-rule:before { content: '\e818'; } /* '' */
.bpmn-icon-sub-process-marker:before { content: '\e819'; } /* '' */
.bpmn-icon-start-event-parallel-multiple:before { content: '\e81a'; } /* '' */
.bpmn-icon-start-event-error:before { content: '\e81b'; } /* '' */
.bpmn-icon-intermediate-event-catch-signal:before { content: '\e81c'; } /* '' */
.bpmn-icon-intermediate-event-catch-error:before { content: '\e81d'; } /* '' */
.bpmn-icon-end-event-compensation:before { content: '\e81e'; } /* '' */
.bpmn-icon-subprocess-collapsed:before { content: '\e81f'; } /* '' */
.bpmn-icon-subprocess-expanded:before { content: '\e820'; } /* '' */
.bpmn-icon-task:before { content: '\e821'; } /* '' */
.bpmn-icon-end-event-error:before { content: '\e822'; } /* '' */
.bpmn-icon-intermediate-event-catch-escalation:before { content: '\e823'; } /* '' */
.bpmn-icon-intermediate-event-catch-timer:before { content: '\e824'; } /* '' */
.bpmn-icon-start-event-escalation:before { content: '\e825'; } /* '' */
.bpmn-icon-start-event-signal:before { content: '\e826'; } /* '' */
.bpmn-icon-business-rule-task:before { content: '\e827'; } /* '' */
.bpmn-icon-manual:before { content: '\e828'; } /* '' */
.bpmn-icon-receive:before { content: '\e829'; } /* '' */
.bpmn-icon-call-activity:before { content: '\e82a'; } /* '' */
.bpmn-icon-start-event-timer:before { content: '\e82b'; } /* '' */
.bpmn-icon-start-event-message:before { content: '\e82c'; } /* '' */
.bpmn-icon-intermediate-event-none:before { content: '\e82d'; } /* '' */
.bpmn-icon-intermediate-event-catch-link:before { content: '\e82e'; } /* '' */
.bpmn-icon-end-event-escalation:before { content: '\e82f'; } /* '' */
.bpmn-icon-text-annotation:before { content: '\e830'; } /* '' */
.bpmn-icon-bpmn-io:before { content: '\e831'; } /* '' */
.bpmn-icon-gateway-complex:before { content: '\e832'; } /* '' */
.bpmn-icon-gateway-eventbased:before { content: '\e833'; } /* '' */
.bpmn-icon-gateway-none:before { content: '\e834'; } /* '' */
.bpmn-icon-gateway-or:before { content: '\e835'; } /* '' */
.bpmn-icon-end-event-terminate:before { content: '\e836'; } /* '' */
.bpmn-icon-end-event-signal:before { content: '\e837'; } /* '' */
.bpmn-icon-end-event-none:before { content: '\e838'; } /* '' */
.bpmn-icon-end-event-multiple:before { content: '\e839'; } /* '' */
.bpmn-icon-end-event-message:before { content: '\e83a'; } /* '' */
.bpmn-icon-end-event-link:before { content: '\e83b'; } /* '' */
.bpmn-icon-intermediate-event-catch-message:before { content: '\e83c'; } /* '' */
.bpmn-icon-intermediate-event-throw-compensation:before { content: '\e83d'; } /* '' */
.bpmn-icon-start-event-multiple:before { content: '\e83e'; } /* '' */
.bpmn-icon-script:before { content: '\e83f'; } /* '' */
.bpmn-icon-manual-task:before { content: '\e840'; } /* '' */
.bpmn-icon-send:before { content: '\e841'; } /* '' */
.bpmn-icon-service:before { content: '\e842'; } /* '' */
.bpmn-icon-receive-task:before { content: '\e843'; } /* '' */
.bpmn-icon-user:before { content: '\e844'; } /* '' */
.bpmn-icon-start-event-none:before { content: '\e845'; } /* '' */
.bpmn-icon-intermediate-event-throw-escalation:before { content: '\e846'; } /* '' */
.bpmn-icon-intermediate-event-catch-multiple:before { content: '\e847'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-escalation:before { content: '\e848'; } /* '' */
.bpmn-icon-intermediate-event-throw-link:before { content: '\e849'; } /* '' */
.bpmn-icon-start-event-non-interrupting-condition:before { content: '\e84a'; } /* '' */
.bpmn-icon-data-object:before { content: '\e84b'; } /* '' */
.bpmn-icon-script-task:before { content: '\e84c'; } /* '' */
.bpmn-icon-send-task:before { content: '\e84d'; } /* '' */
.bpmn-icon-data-store:before { content: '\e84e'; } /* '' */
.bpmn-icon-start-event-non-interrupting-escalation:before { content: '\e84f'; } /* '' */
.bpmn-icon-intermediate-event-throw-message:before { content: '\e850'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-multiple:before { content: '\e851'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-signal:before { content: '\e852'; } /* '' */
.bpmn-icon-intermediate-event-throw-multiple:before { content: '\e853'; } /* '' */
.bpmn-icon-start-event-non-interrupting-message:before { content: '\e854'; } /* '' */
.bpmn-icon-ad-hoc-marker:before { content: '\e855'; } /* '' */
.bpmn-icon-service-task:before { content: '\e856'; } /* '' */
.bpmn-icon-task-none:before { content: '\e857'; } /* '' */
.bpmn-icon-compensation-marker:before { content: '\e858'; } /* '' */
.bpmn-icon-start-event-non-interrupting-multiple:before { content: '\e859'; } /* '' */
.bpmn-icon-intermediate-event-throw-signal:before { content: '\e85a'; } /* '' */
.bpmn-icon-intermediate-event-catch-non-interrupting-condition:before { content: '\e85b'; } /* '' */
.bpmn-icon-participant:before { content: '\e85c'; } /* '' */
.bpmn-icon-event-subprocess-expanded:before { content: '\e85d'; } /* '' */
.bpmn-icon-lane-insert-below:before { content: '\e85e'; } /* '' */
.bpmn-icon-space-tool:before { content: '\e85f'; } /* '' */
.bpmn-icon-connection-multi:before { content: '\e860'; } /* '' */
.bpmn-icon-lane:before { content: '\e861'; } /* '' */
.bpmn-icon-lasso-tool:before { content: '\e862'; } /* '' */
.bpmn-icon-lane-insert-above:before { content: '\e863'; } /* '' */
.bpmn-icon-lane-divide-three:before { content: '\e864'; } /* '' */
.bpmn-icon-lane-divide-two:before { content: '\e865'; } /* '' */
.bpmn-icon-data-input:before { content: '\e866'; } /* '' */
.bpmn-icon-data-output:before { content: '\e867'; } /* '' */
.bpmn-icon-hand-tool:before { content: '\e868'; } /* '' */
.bpmn-icon-group:before { content: '\e869'; } /* '' */
.bpmn-icon-transaction:before { content: '\e8c4'; } /* '' */
\ No newline at end of file
{
"name": "bpmn-js-example-properties-panel",
"version": "0.0.0",
"description": "A bpmn-js modeler + properties panel example",
"main": "app/index.js",
"scripts": {
"all": "grunt",
"dev": "grunt auto-build"
},
"repository": {
"type": "git",
"url": "https://github.com/bpmn-io/bpmn-js-examples"
},
"keywords": [
"bpmnjs-example"
],
"author": {
"name": "Nico Rehwaldt",
"url": "https://github.com/nikku"
},
"contributors": [
{
"name": "bpmn.io contributors",
"url": "https://github.com/bpmn-io"
}
],
"license": "MIT",
"devDependencies": {
"esmify": "^2.1.1",
"grunt": "^1.0.4",
"grunt-browserify": "^5.3.0",
"grunt-contrib-connect": "^2.0.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-less": "^2.0.0",
"grunt-contrib-watch": "^1.1.0",
"load-grunt-tasks": "^5.0.0",
"stringify": "^5.2.0"
},
"dependencies": {
"bpmn-js": "^7.0.0",
"bpmn-js-properties-panel": "^0.32.0",
"camunda-bpmn-moddle": "^4.0.1",
"diagram-js": "^5.0.0",
"jquery": "^3.4.1",
"min-dash": "^3.5.0",
"x2js": "^3.4.0"
}
}
export default class CustomContextPad {
constructor(config, contextPad, create, elementFactory, injector, translate) {
this.create = create;
this.elementFactory = elementFactory;
this.translate = translate;
//自动摆放位置
if (config.autoPlace !== false) {
this.autoPlace = injector.get('autoPlace', false);
}
//注册工具
contextPad.registerProvider(this);
}
getContextPadEntries(element) {
const {
autoPlace,
create,
elementFactory,
translate
} = this;
function appendUserTask(event, element) {
if (autoPlace) {
const shape = elementFactory.createShape({ type: 'bpmn:UserTask' });
autoPlace.append(element, shape);
} else {
appendUserTaskStart(event, element);
}
}
function appendUserTaskStart(event) {
const shape = elementFactory.createShape({ type: 'bpmn:UserTask' });
create.start(event, shape, element);
}
function appendCallActivityStart(event) {
const shape = elementFactory.createShape({ type: 'bpmn:CallActivity' });
create.start(event, shape, element);
}
function appendCallActivity(event, element) {
if (autoPlace) {
const shape = elementFactory.createShape({ type: 'bpmn:CallActivity' });
autoPlace.append(element, shape);
} else {
appendCallActivityStart(event, element);
}
}
return {
'append.user-task': {
group: 'model',
className: 'bpmn-icon-user-task',
title: translate('Append ServiceTask'),
action: {
click: appendUserTask,
dragstart: appendUserTaskStart
}
},
'append.call-activity':{
group: 'model',
className: 'bpmn-icon-call-activity',
title: translate('Append CallActivity'),
action: {
click: appendCallActivity,
dragstart: appendCallActivityStart
}
}
};
}
}
CustomContextPad.$inject = [
'config',
'contextPad',
'create',
'elementFactory',
'injector',
'translate'
];
\ No newline at end of file
export default class CustomPalette {
constructor(create, elementFactory, palette, translate) {
this.create = create;
this.elementFactory = elementFactory;
this.translate = translate;
palette.registerProvider(this);
}
getPaletteEntries(element) {
const {
create,
elementFactory,
translate
} = this;
function createServiceTask(event) {
const shape = elementFactory.createShape({ type: 'bpmn:UserTask' });
create.start(event, shape);
}
function createCallActivity(event) {
const shape = elementFactory.createShape({ type: 'bpmn:CallActivity' });
create.start(event, shape);
}
return {
'create.user-task': {
group: 'activity',
className: 'bpmn-icon-user-task',
title: translate('Create UserTask'),
action: {
dragstart: createServiceTask,
click: createServiceTask
}
},
'create.call-activity': {
group: 'activity',
className: 'bpmn-icon-call-activity',
title: translate('Create CallActivity'),
action: {
dragstart: createCallActivity,
click: createCallActivity
}
}
}
}
}
CustomPalette.$inject = [
'create',
'elementFactory',
'palette',
'translate'
];
\ No newline at end of file
import CustomContextPad from './CustomContextPad';
import CustomPalette from './CustomPalette';
export default {
__init__: [ 'customContextPad', 'customPalette' ],
customContextPad: [ 'type', CustomContextPad ],
customPalette: [ 'type', CustomPalette ]
};
\ No newline at end of file
import translations from './translationsGerman';
export default function customTranslate(template, replacements) {
replacements = replacements || {};
template = translations[template] || template;
return template.replace(/{([^}]+)}/g, function(_, key) {
var str = replacements[key];
if(translations[replacements[key]] != null && translations [replacements[key]] != 'undefined'){
str = translations[replacements[key]];
}
return str || '{' + key + '}';
});
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="sample-diagram" targetNamespace="http://activiti.org/bpmn">
<bpmn2:process id="Process_1" isExecutable="false">
<bpmn2:startEvent id="StartEvent_1"/>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds height="36.0" width="36.0" x="412.0" y="240.0"/>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>
\ No newline at end of file
'use strict';
var DEFAULT_PRIORITY = 1000;
/**
* A component that decides upon the visibility / editable
* state of properties in the properties panel.
*
* Implementors must subclass this component and override
* {@link PropertiesActivator#isEntryVisible} and
* {@link PropertiesActivator#isPropertyEditable} to provide
* custom behavior.
*
* @class
* @constructor
*
* @param {EventBus} eventBus
* @param {Number} [priority] at which priority to hook into the activation
*/
function PropertiesActivator(eventBus, priority) {
var self = this;
priority = priority || DEFAULT_PRIORITY;
eventBus.on('propertiesPanel.isEntryVisible', priority, function(e) {
return self.isEntryVisible(e.entry, e.element);
});
eventBus.on('propertiesPanel.isPropertyEditable', priority, function(e) {
return self.isPropertyEditable(e.entry, e.propertyName, e.element);
});
}
PropertiesActivator.$inject = [ 'eventBus' ];
module.exports = PropertiesActivator;
/**
* Should the given entry be visible for the specified element.
*
* @method PropertiesActivator#isEntryVisible
*
* @param {EntryDescriptor} entry
* @param {ModdleElement} element
*
* @returns {Boolean}
*/
PropertiesActivator.prototype.isEntryVisible = function(entry, element) {
return true;
};
/**
* Should the given property be editable for the specified element
*
* @method PropertiesActivator#isPropertyEditable
*
* @param {EntryDescriptor} entry
* @param {String} propertyName
* @param {ModdleElement} element
*
* @returns {Boolean}
*/
PropertiesActivator.prototype.isPropertyEditable = function(entry, propertyName, element) {
return true;
};
\ No newline at end of file
'use strict';
var forEach = require('lodash/forEach');
/**
* A handler that combines and executes multiple commands.
*
* All updates are bundled on the command stack and executed in one step.
* This also makes it possible to revert the changes in one step.
*
* Example use case: remove the camunda:formKey attribute and in addition
* add all form fields needed for the camunda:formData property.
*
* @class
* @constructor
*/
function MultiCommandHandler(commandStack) {
this._commandStack = commandStack;
}
MultiCommandHandler.$inject = [ 'commandStack' ];
module.exports = MultiCommandHandler;
MultiCommandHandler.prototype.preExecute = function(context) {
var commandStack = this._commandStack;
forEach(context, function(command) {
commandStack.execute(command.cmd, command.context);
});
};
\ No newline at end of file
module.exports = {
__depends__: [
require('./index'),
require('diagram-js/lib/i18n/translate').default
],
__init__: [ 'propertiesPanel' ],
propertiesPanel: [ 'type', require('./PropertiesPanel') ]
};
module.exports = {
__depends__: [
require('./cmd/index'),
require('diagram-js/lib/i18n/translate').default
],
__init__: [
'customElementsPropertiesActivator',
'elementTemplatesLoader'
],
customElementsPropertiesActivator: [ 'type', require('./CustomElementsPropertiesActivator') ],
elementTemplates: [ 'type', require('./ElementTemplates') ],
elementTemplatesLoader: [ 'type', require('./ElementTemplatesLoader') ]
};
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册