瀏覽代碼

优化工作流配置

zhouhao 6 年之前
父節點
當前提交
aa7dbdb8c3
共有 22 個文件被更改,包括 612 次插入96 次删除
  1. 14 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/pom.xml
  2. 11 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dao/ActivityConfigDao.java
  3. 12 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dao/ProcessDefineConfigDao.java
  4. 17 5
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/entity/ActivityConfigEntity.java
  5. 20 1
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/entity/ProcessDefineConfigEntity.java
  6. 18 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dimension/DefaultPermissionDimensionParser.java
  7. 4 5
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dimension/DimensionContext.java
  8. 3 8
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dimension/parser/RelationCandidateDimensionParserStrategy.java
  9. 0 57
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/entity/SimpleProcessDefinition.java
  10. 3 1
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/flowable/FlowableAutoConfiguration.java
  11. 17 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/ActivityConfigService.java
  12. 18 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/ProcessDefineConfigService.java
  13. 4 2
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/config/ActivityConfiguration.java
  14. 2 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/config/ProcessConfiguration.java
  15. 88 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/ActivityConfigServiceImpl.java
  16. 3 4
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmTaskServiceImpl.java
  17. 115 5
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/ProcessConfigurationServiceImpl.java
  18. 90 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/ProcessDefineConfigServiceImpl.java
  19. 0 8
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/web/FlowableDeploymentController.java
  20. 64 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/resources/hsweb-starter.js
  21. 55 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/resources/org/hswebframework/web/dao/mybatis/mappers/workflow/ActivityConfigMapper.xml
  22. 54 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/resources/org/hswebframework/web/dao/mybatis/mappers/workflow/ProcessDefineConfigMapper.xml

+ 14 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/pom.xml

@@ -12,8 +12,22 @@
 
     <artifactId>hsweb-system-workflow-local</artifactId>
 
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+    </build>
     <dependencies>
 
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-commons-dao-mybatis</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
         <dependency>
             <groupId>org.hswebframework.web</groupId>
             <artifactId>hsweb-commons-service-simple</artifactId>

+ 11 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dao/ActivityConfigDao.java

@@ -0,0 +1,11 @@
+package org.hswebframework.web.workflow.dao;
+
+import org.hswebframework.web.dao.CrudDao;
+import org.hswebframework.web.workflow.dao.entity.ActivityConfigEntity;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+public interface ActivityConfigDao extends CrudDao<ActivityConfigEntity, String> {
+}

+ 12 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dao/ProcessDefineConfigDao.java

@@ -0,0 +1,12 @@
+package org.hswebframework.web.workflow.dao;
+
+import org.hswebframework.web.dao.CrudDao;
+import org.hswebframework.web.workflow.dao.entity.ProcessDefineConfigEntity;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+public interface ProcessDefineConfigDao extends CrudDao<ProcessDefineConfigEntity, String> {
+
+}

+ 17 - 5
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/entity/ActivityConfigEntity.java

@@ -1,4 +1,4 @@
-package org.hswebframework.web.workflow.entity;
+package org.hswebframework.web.workflow.dao.entity;
 
 import lombok.Getter;
 import lombok.Setter;
@@ -6,16 +6,27 @@ import org.hibernate.validator.constraints.NotBlank;
 import org.hswebframework.web.commons.entity.SimpleGenericEntity;
 import org.hswebframework.web.validator.group.CreateGroup;
 
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
 @Getter
 @Setter
 public class ActivityConfigEntity extends SimpleGenericEntity<String> {
 
+    private static final long serialVersionUID = 2909584456889604626L;
+
     /**
      * 节点ID
      */
     @NotBlank(groups = CreateGroup.class)
     private String activityId;
 
+    /**
+     * 流程定义key
+     */
+    @NotBlank(groups = CreateGroup.class)
+    private String processDefineKey;
+
     /**
      * 流程定义ID
      */
@@ -37,10 +48,11 @@ public class ActivityConfigEntity extends SimpleGenericEntity<String> {
      */
     private String candidateDimension;
 
-    /**
-     * 版本号
-     */
-    private Long version;
+    @NotNull(groups = CreateGroup.class)
+    private Date createTime;
 
+    private Date updateTime;
 
+    @NotNull(groups = CreateGroup.class)
+    private Byte status;
 }

+ 20 - 1
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/entity/ProcessDefineConfigEntity.java

@@ -1,4 +1,4 @@
-package org.hswebframework.web.workflow.entity;
+package org.hswebframework.web.workflow.dao.entity;
 
 import lombok.Getter;
 import lombok.Setter;
@@ -6,10 +6,20 @@ import org.hibernate.validator.constraints.NotBlank;
 import org.hswebframework.web.commons.entity.SimpleGenericEntity;
 import org.hswebframework.web.validator.group.CreateGroup;
 
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
 @Getter
 @Setter
 public class ProcessDefineConfigEntity extends SimpleGenericEntity<String> {
 
+    private static final long serialVersionUID = -140312693789656665L;
+    /**
+     * 流程定义Key
+     */
+    @NotBlank(groups = CreateGroup.class)
+    private String processDefineKey;
+
     /**
      * 流程定义ID
      */
@@ -32,4 +42,13 @@ public class ProcessDefineConfigEntity extends SimpleGenericEntity<String> {
      */
     private String permissionDimension;
 
+    private Date createTime;
+
+    private Date updateTime;
+
+    /**
+     * 状态
+     */
+    @NotNull(groups = CreateGroup.class)
+    private Byte status;
 }

+ 18 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dimension/DefaultPermissionDimensionParser.java

@@ -0,0 +1,18 @@
+package org.hswebframework.web.workflow.dimension;
+
+import org.hswebframework.web.authorization.AuthenticationPredicate;
+import org.hswebframework.web.authorization.AuthenticationUtils;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+@Component
+public class DefaultPermissionDimensionParser implements PermissionDimensionParser {
+    @Override
+    public AuthenticationPredicate parse(String jsonConfig) {
+
+        return AuthenticationUtils.createPredicate(jsonConfig);
+    }
+}

+ 4 - 5
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dimension/DimensionContext.java

@@ -20,13 +20,12 @@ public class DimensionContext {
      */
     private String creatorId;
 
-    /**
-     * 当前环节
-     */
-    private TaskInfo currentTask;
+    private String processDefineId;
+
+    private String activityId;
 
     /**
      * 上一环节
      */
-    private TaskInfo preTask;
+    private TaskInfo task;
 }

+ 3 - 8
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/dimension/parser/RelationCandidateDimensionParserStrategy.java

@@ -29,10 +29,10 @@ import java.util.stream.Collectors;
  */
 @Slf4j
 @ConditionalOnBean(RelationsManager.class)
-public class RelationCandidateDimensionParserStrategy implements CandidateDimensionParserStrategy {
+public class ScriptCandiateDimensionParserStrategy implements CandidateDimensionParserStrategy {
 
     @Autowired
-    RelationsManager relationsManager;
+    private RelationsManager relationsManager;
 
     @Override
     public boolean support(String dimension) {
@@ -50,11 +50,8 @@ public class RelationCandidateDimensionParserStrategy implements CandidateDimens
             return Collections.emptyList();
         }
 
-        String preId = context.getPreTask().getOwner();
         String creatorId = context.getCreatorId();
 
-        Supplier<PersonRelations> pre = () -> relationsManager.getPersonRelationsByUserId(preId);
-
         Supplier<PersonRelations> creator = () -> relationsManager.getPersonRelationsByUserId(creatorId);
 
         DynamicScriptEngine engine = DynamicScriptEngineFactory.getEngine(expressionLanguage);
@@ -69,9 +66,7 @@ public class RelationCandidateDimensionParserStrategy implements CandidateDimens
         }
 
         Object obj = engine.execute(id, Maps.<String, Object>buildMap()
-                .put("pre", pre)
-                .put("creator", creator)
-                .put("preId", preId)
+                .put("user", creator)
                 .put("creatorId", creatorId)
                 .put("context", context)
                 .get())

+ 0 - 57
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/entity/SimpleProcessDefinition.java

@@ -1,57 +0,0 @@
-package org.hswebframework.web.workflow.entity;
-
-import lombok.Getter;
-import lombok.Setter;
-import org.activiti.engine.repository.ProcessDefinition;
-import org.hswebframework.web.commons.bean.Bean;
-
-/**
- * @author zhouhao
- */
-@Getter
-@Setter
-public class SimpleProcessDefinition implements Bean {
-
-    private static final long serialVersionUID = -7246626050183062980L;
-
-    private String  id;
-    private String  category;
-    private String  name;
-    private String  key;
-    private String  description;
-    private int     version;
-    private String  resourceName;
-    private String  deploymentId;
-    private String  diagramResourceName;
-    private boolean suspended;
-    private boolean hasStartFormKey;
-    private boolean hasGraphicalNotation;
-    private String  tenantId;
-
-    public SimpleProcessDefinition() {
-    }
-
-    public SimpleProcessDefinition(ProcessDefinition definition) {
-        id = definition.getId();
-        category = definition.getCategory();
-        name = definition.getName();
-        key = definition.getKey();
-        description = definition.getDescription();
-        version = definition.getVersion();
-
-        resourceName = definition.getResourceName();
-        deploymentId = definition.getDeploymentId();
-        diagramResourceName = definition.getResourceName();
-
-        suspended = definition.isSuspended();
-
-        hasGraphicalNotation = definition.hasGraphicalNotation();
-        hasStartFormKey = definition.hasStartFormKey();
-        tenantId = definition.getTenantId();
-    }
-
-    public void setSuspended(boolean suspended) {
-        this.suspended = suspended;
-    }
-
-}

+ 3 - 1
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/flowable/FlowableAutoConfiguration.java

@@ -2,17 +2,18 @@ package org.hswebframework.web.workflow.flowable;
 
 import org.activiti.engine.impl.interceptor.SessionFactory;
 import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
+import org.hswebframework.web.dao.Dao;
 import org.hswebframework.web.service.authorization.UserService;
 import org.hswebframework.web.workflow.flowable.utils.CustomGroupEntityManager;
 import org.hswebframework.web.workflow.flowable.utils.CustomGroupEntityManagerFactory;
 import org.hswebframework.web.workflow.flowable.utils.CustomUserEntityManager;
 import org.hswebframework.web.workflow.flowable.utils.CustomUserEntityManagerFactory;
+import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.AutoConfigureAfter;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.transaction.PlatformTransactionManager;
 
 import java.util.List;
 
@@ -21,6 +22,7 @@ import java.util.List;
  */
 @Configuration
 @AutoConfigureAfter(FlowableAutoConfiguration.CustomEntityManagerAutoConfiguration.class)
+@MapperScan(value = "org.hswebframework.web.workflow.dao", markerInterface = Dao.class)
 public class FlowableAutoConfiguration {
 
     @Autowired(required = false)

+ 17 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/ActivityConfigService.java

@@ -0,0 +1,17 @@
+package org.hswebframework.web.workflow.service;
+
+import org.hswebframework.web.service.CrudService;
+import org.hswebframework.web.workflow.dao.entity.ActivityConfigEntity;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+public interface ActivityConfigService extends CrudService<ActivityConfigEntity, String> {
+
+    ActivityConfigEntity selectByProcessDefineIdAndActivityId(String processDefineId, String activityId);
+
+    ActivityConfigEntity selectByProcessDefineKeyAndActivityId(String processDefineKey, String activityId);
+
+
+}

+ 18 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/ProcessDefineConfigService.java

@@ -0,0 +1,18 @@
+package org.hswebframework.web.workflow.service;
+
+import org.hswebframework.web.service.CrudService;
+import org.hswebframework.web.workflow.dao.entity.ActivityConfigEntity;
+import org.hswebframework.web.workflow.dao.entity.ProcessDefineConfigEntity;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+public interface ProcessDefineConfigService extends CrudService<ProcessDefineConfigEntity, String> {
+
+    ProcessDefineConfigEntity selectByProcessDefineId(String processDefineId);
+
+    ProcessDefineConfigEntity selectByLatestProcessDefineKey(String processDefineKey);
+
+
+}

+ 4 - 2
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/config/ActivityConfiguration.java

@@ -1,5 +1,7 @@
 package org.hswebframework.web.workflow.service.config;
 
+import org.activiti.engine.runtime.ProcessInstance;
+import org.activiti.engine.task.Task;
 import org.hswebframework.web.authorization.User;
 
 import java.util.List;
@@ -26,13 +28,13 @@ public interface ActivityConfiguration {
      * @see User
      * @see org.hswebframework.web.authorization.Authentication
      */
-    boolean canClaim(String userId);
+    boolean canClaim(Task task,String userId);
 
     /**
      * 获取此任务的所有候选人信息
      *
      * @return 此任务的所有候选人信息 {@link CandidateInfo}
      */
-    List<CandidateInfo> getCandidateInfo();
+    List<CandidateInfo> getCandidateInfo(Task task);
 
 }

+ 2 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/config/ProcessConfiguration.java

@@ -11,4 +11,6 @@ public interface ProcessConfiguration {
     String getFormId();
 
     void assertCanStartProcess(String userId, ProcessDefinition definition);
+
+    boolean canStartProcess(String userId, ProcessDefinition definition);
 }

+ 88 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/ActivityConfigServiceImpl.java

@@ -0,0 +1,88 @@
+package org.hswebframework.web.workflow.service.imp;
+
+import org.hswebframework.web.dao.CrudDao;
+import org.hswebframework.web.id.IDGenerator;
+import org.hswebframework.web.service.EnableCacheGenericEntityService;
+import org.hswebframework.web.service.GenericEntityService;
+import org.hswebframework.web.workflow.dao.ActivityConfigDao;
+import org.hswebframework.web.workflow.dao.entity.ActivityConfigEntity;
+import org.hswebframework.web.workflow.service.ActivityConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.cache.annotation.Caching;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+@Service
+@CacheConfig(cacheNames = "process-activity-config")
+public class ActivityConfigServiceImpl extends GenericEntityService<ActivityConfigEntity, String>
+        implements ActivityConfigService {
+
+    @Autowired
+    private ActivityConfigDao activityConfigDao;
+
+    @Override
+    protected IDGenerator<String> getIDGenerator() {
+        return IDGenerator.MD5;
+    }
+
+    @Override
+    public CrudDao<ActivityConfigEntity, String> getDao() {
+        return activityConfigDao;
+    }
+
+    @Override
+    @Caching(evict = {
+            @CacheEvict(key = "'define-id:'+#entity.processDefineId+'-'+#entity.activityId"),
+            @CacheEvict(key = "'define-key:'+#entity.processDefineKey+'-'+#entity.activityId")
+    })
+    public String insert(ActivityConfigEntity entity) {
+        entity.setCreateTime(new Date());
+        entity.setUpdateTime(new Date());
+        return super.insert(entity);
+    }
+
+    @Override
+    @Caching(evict = {
+            @CacheEvict(key = "'define-id:'+#entity.processDefineId+'-'+#entity.activityId"),
+            @CacheEvict(key = "'define-key:'+#entity.processDefineKey+'-'+#entity.activityId")
+    })
+    public int updateByPk(String pk, ActivityConfigEntity entity) {
+        entity.setUpdateTime(new Date());
+        return super.updateByPk(pk, entity);
+    }
+
+    @Override
+    @Caching(evict = {
+            @CacheEvict(key = "'define-id:'+#result.processDefineId+'-'+#result.activityId", condition = "#result!=null"),
+            @CacheEvict(key = "'define-key:'+#result.processDefineKey+'-'+#result.activityId", condition = "#result!=null")
+    })
+    public ActivityConfigEntity deleteByPk(String id) {
+        return super.deleteByPk(id);
+    }
+
+    @Override
+    @Cacheable(key = "'define-id:'+#processDefineId+'-'+#activityId")
+    public ActivityConfigEntity selectByProcessDefineIdAndActivityId(String processDefineId, String activityId) {
+        return createQuery()
+                .where("processDefineId", processDefineId)
+                .and("activityId", activityId)
+                .single();
+    }
+
+    @Override
+    @Cacheable(key = "'define-key:'+#processDefineKey+'-'+#activityId")
+    public ActivityConfigEntity selectByProcessDefineKeyAndActivityId(String processDefineKey, String activityId) {
+        return createQuery()
+                .where("processDefineKey", processDefineKey)
+                .and("activityId", activityId)
+                .single();
+    }
+}

+ 3 - 4
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/BpmTaskServiceImpl.java

@@ -287,10 +287,9 @@ public class BpmTaskServiceImpl extends AbstractFlowableService implements BpmTa
         if (task.getTaskDefinitionKey() != null) {
             //从配置中获取候选人
             List<CandidateInfo> candidateInfoList = processConfigurationService
-                    .getActivityConfiguration(doingUserId
-                            , task.getProcessDefinitionId()
-                            , task.getTaskDefinitionKey())
-                    .getCandidateInfo();
+                    .getActivityConfiguration(doingUserId, task.getProcessDefinitionId(), task.getTaskDefinitionKey())
+                    .getCandidateInfo(task);
+
             for (CandidateInfo candidateInfo : candidateInfoList) {
                 taskService.addCandidateUser(task.getId(), candidateInfo.user().getUser().getId());
             }

+ 115 - 5
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/ProcessConfigurationServiceImpl.java

@@ -1,14 +1,32 @@
 package org.hswebframework.web.workflow.service.imp;
 
+import io.vavr.Lazy;
 import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.task.Task;
+import org.hswebframework.web.authorization.Authentication;
+import org.hswebframework.web.authorization.AuthenticationHolder;
+import org.hswebframework.web.authorization.AuthenticationPredicate;
+import org.hswebframework.web.authorization.exception.AccessDenyException;
+import org.hswebframework.web.organizational.authorization.PersonnelAuthentication;
+import org.hswebframework.web.organizational.authorization.PersonnelAuthenticationHolder;
+import org.hswebframework.web.workflow.dao.entity.ActivityConfigEntity;
+import org.hswebframework.web.workflow.dao.entity.ProcessDefineConfigEntity;
+import org.hswebframework.web.workflow.dimension.CandidateDimension;
+import org.hswebframework.web.workflow.dimension.CandidateDimensionParser;
+import org.hswebframework.web.workflow.dimension.DimensionContext;
+import org.hswebframework.web.workflow.dimension.PermissionDimensionParser;
+import org.hswebframework.web.workflow.service.ActivityConfigService;
+import org.hswebframework.web.workflow.service.ProcessDefineConfigService;
 import org.hswebframework.web.workflow.service.config.ProcessConfigurationService;
 import org.hswebframework.web.workflow.service.config.CandidateInfo;
 import org.hswebframework.web.workflow.service.config.ActivityConfiguration;
 import org.hswebframework.web.workflow.service.config.ProcessConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 
 /**
@@ -18,18 +36,105 @@ import java.util.List;
 @Service
 public class ProcessConfigurationServiceImpl implements ProcessConfigurationService {
 
+    @Autowired
+    private ProcessDefineConfigService defineConfigService;
+
+    @Autowired
+    private ActivityConfigService activityConfigService;
+
+    @Autowired
+    private PermissionDimensionParser permissionDimensionParser;
+
+    @Autowired
+    private CandidateDimensionParser candidateDimensionParser;
+
+
     static final EmptyActivityConfiguration emptyConfiguration = new EmptyActivityConfiguration();
 
     @Override
     public ActivityConfiguration getActivityConfiguration(String doingUser, String processDefineId, String activityId) {
+        ActivityConfigEntity configEntity = activityConfigService.selectByProcessDefineIdAndActivityId(processDefineId, activityId);
+        if (configEntity == null) {
+            return emptyConfiguration;
+        }
+
+        return new ActivityConfiguration() {
+            @Override
+            public String getFormId() {
+                return configEntity.getFormId();
+            }
+
+            @Override
+            public boolean canClaim(Task task, String userId) {
+                return getCandidateInfo(task)
+                        .stream()
+                        .map(CandidateInfo::user)
+                        .anyMatch(user -> user.getUser().getId().equals(userId));
+            }
+
+            @Override
+            @SuppressWarnings("all")
+            public List<CandidateInfo> getCandidateInfo(Task task) {
+                return Lazy.val(() -> {
+
+                    DimensionContext context = new DimensionContext();
+                    context.setCreatorId(doingUser);
+                    context.setActivityId(activityId);
+                    context.setProcessDefineId(processDefineId);
+                    context.setTask(task);
 
-        return emptyConfiguration;
+                    CandidateDimension dimension = candidateDimensionParser
+                            .parse(context, configEntity.getCandidateDimension());
+
+                    return dimension.getCandidateUserIdList()
+                            .stream()
+                            .map(userId ->
+                                    Lazy.val(() -> new CandidateInfo() {
+                                        @Override
+                                        public Authentication user() {
+                                            return Lazy.val(() -> AuthenticationHolder.get(userId), Authentication.class);
+                                        }
+
+                                        @Override
+                                        public PersonnelAuthentication person() {
+                                            return Lazy.val(() -> PersonnelAuthenticationHolder.getByUserId(userId), PersonnelAuthentication.class);
+                                        }
+                                    }, CandidateInfo.class))
+                            .collect(Collectors.toList());
+
+                }, List.class);
+            }
+        };
     }
 
     @Override
     public ProcessConfiguration getProcessConfiguration(String processDefineId) {
+        ProcessDefineConfigEntity entity = defineConfigService.selectByProcessDefineId(processDefineId);
+        if (entity == null) {
+            return emptyConfiguration;
+        }
+        return new ProcessConfiguration() {
+            @Override
+            public String getFormId() {
+                return entity.getFormId();
+            }
+
+            @Override
+            public void assertCanStartProcess(String userId, ProcessDefinition definition) {
+                if (!canStartProcess(userId, definition)) {
+                    throw new AccessDenyException("没有权限启动此流程");
+                }
+            }
 
-        return emptyConfiguration;
+            @Override
+            public boolean canStartProcess(String userId, ProcessDefinition definition) {
+                AuthenticationPredicate predicate = permissionDimensionParser.parse(entity.getPermissionDimension());
+                if (null != predicate) {
+                    return predicate.test(AuthenticationHolder.get(userId));
+                }
+                return true;
+            }
+        };
     }
 
     private final static class EmptyActivityConfiguration implements ActivityConfiguration, ProcessConfiguration {
@@ -40,18 +145,23 @@ public class ProcessConfigurationServiceImpl implements ProcessConfigurationServ
         }
 
         @Override
-        public boolean canClaim(String userId) {
+        public boolean canClaim(Task task, String userId) {
             return false;
         }
 
         @Override
-        public List<CandidateInfo> getCandidateInfo() {
+        public List<CandidateInfo> getCandidateInfo(Task task) {
             return Collections.emptyList();
         }
 
         @Override
         public void assertCanStartProcess(String userId, ProcessDefinition definition) {
-            
+            throw new AccessDenyException("没有权限启动此流程:" + definition.getName() + "(" + definition.getId() + ")");
+        }
+
+        @Override
+        public boolean canStartProcess(String userId, ProcessDefinition definition) {
+            return false;
         }
     }
 }

+ 90 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/service/imp/ProcessDefineConfigServiceImpl.java

@@ -0,0 +1,90 @@
+package org.hswebframework.web.workflow.service.imp;
+
+import org.hswebframework.web.commons.entity.DataStatus;
+import org.hswebframework.web.dao.CrudDao;
+import org.hswebframework.web.id.IDGenerator;
+import org.hswebframework.web.service.EnableCacheGenericEntityService;
+import org.hswebframework.web.workflow.dao.ProcessDefineConfigDao;
+import org.hswebframework.web.workflow.dao.entity.ProcessDefineConfigEntity;
+import org.hswebframework.web.workflow.service.ProcessDefineConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Caching;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * @author zhouhao
+ * @since 3.0.0-RC
+ */
+@Service
+@CacheConfig(cacheNames = "process-config")
+public class ProcessDefineConfigServiceImpl extends EnableCacheGenericEntityService<ProcessDefineConfigEntity, String>
+        implements ProcessDefineConfigService {
+
+    @Autowired
+    private ProcessDefineConfigDao processDefineConfigDao;
+
+    @Override
+    protected IDGenerator<String> getIDGenerator() {
+        return IDGenerator.MD5;
+    }
+
+    @Override
+    public CrudDao<ProcessDefineConfigEntity, String> getDao() {
+        return processDefineConfigDao;
+    }
+
+
+    @Override
+    @Caching(evict = {
+            @CacheEvict(key = "'define-id:'+#entity.processDefineId"),
+            @CacheEvict(key = "'define-key-latest:'+#entity.processDefineKey", condition = "#entity.status==1")
+    })
+    public String insert(ProcessDefineConfigEntity entity) {
+        entity.setCreateTime(new Date());
+        entity.setUpdateTime(new Date());
+        return super.insert(entity);
+    }
+
+    @Override
+    @Caching(evict = {
+            @CacheEvict(key = "'define-id:'+#entity.processDefineId"),
+            @CacheEvict(key = "'define-key-latest:'+#entity.processDefineKey")
+    })
+    public int updateByPk(String id, ProcessDefineConfigEntity entity) {
+        entity.setUpdateTime(new Date());
+        return super.updateByPk(id, entity);
+    }
+
+    @Override
+    @Caching(evict = {
+            @CacheEvict(key = "'define-id:'+#result.processDefineId"),
+            @CacheEvict(key = "'define-key-latest:'+#result.processDefineKey")
+    })
+    public ProcessDefineConfigEntity deleteByPk(String id) {
+
+        return super.deleteByPk(id);
+    }
+
+    @Override
+    @CacheEvict(key = "'define-id:'+#processDefineId")
+    public ProcessDefineConfigEntity selectByProcessDefineId(String processDefineId) {
+        return createQuery()
+                .where("processDefineId", Objects.requireNonNull(processDefineId, "参数[processDefineId]不能为空"))
+                .single();
+    }
+
+    @Override
+    @CacheEvict(key = "'define-key-latest:'+#processDefineKey")
+    public ProcessDefineConfigEntity selectByLatestProcessDefineKey(String processDefineKey) {
+        return createQuery()
+                .where("processDefineKey", Objects.requireNonNull(processDefineKey, "参数[processDefineKey]不能为空"))
+                .and("status", DataStatus.STATUS_ENABLED)
+                .orderByDesc("updateTime")
+                .single();
+    }
+}

+ 0 - 8
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/java/org/hswebframework/web/workflow/web/FlowableDeploymentController.java

@@ -1,6 +1,5 @@
 package org.hswebframework.web.workflow.web;
 
-import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import io.swagger.annotations.Api;
@@ -17,16 +16,12 @@ import org.activiti.engine.repository.DeploymentBuilder;
 import org.activiti.engine.repository.ProcessDefinition;
 import org.activiti.engine.repository.ProcessDefinitionQuery;
 import org.apache.commons.io.FilenameUtils;
-import org.hswebframework.ezorm.core.PropertyWrapper;
-import org.hswebframework.ezorm.core.SimplePropertyWrapper;
-import org.hswebframework.ezorm.core.param.TermType;
 import org.hswebframework.web.NotFoundException;
 import org.hswebframework.web.authorization.Permission;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.commons.entity.PagerResult;
 import org.hswebframework.web.commons.entity.param.QueryParamEntity;
 import org.hswebframework.web.controller.message.ResponseMessage;
-import org.hswebframework.web.workflow.entity.SimpleProcessDefinition;
 import org.hswebframework.web.workflow.service.BpmActivityService;
 import org.hswebframework.web.workflow.service.BpmProcessService;
 import org.hswebframework.web.workflow.service.BpmTaskService;
@@ -49,9 +44,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
 import java.util.zip.ZipInputStream;
 
 /**

+ 64 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/resources/hsweb-starter.js

@@ -0,0 +1,64 @@
+//组件信息
+var info = {
+    groupId: "${project.groupId}",
+    artifactId: "${project.artifactId}",
+    version: "${project.version}",
+    website: "https://github.com/hs-web/hsweb-framework",
+    author: "admin@hsweb.me",
+    comment: ""
+};
+
+//版本更新信息
+var versions = [
+    // {
+    //     version: "3.0.2",
+    //     upgrade: function (context) {
+    //         java.lang.System.out.println("更新到3.0.2了");
+    //     }
+    // }
+];
+var JDBCType = java.sql.JDBCType;
+
+function install(context) {
+    var database = context.database;
+    database.createOrAlter("s_wf_proc_conf")
+        .addColumn().name("u_id").alias("id").comment("ID").jdbcType(java.sql.JDBCType.VARCHAR).length(32).primaryKey().commit()
+        .addColumn().name("proc_def_key").alias("processDefineKey").comment("模板定义KEY").jdbcType(java.sql.JDBCType.VARCHAR).length(32).commit()
+        .addColumn().name("proc_def_id").alias("processDefineId").comment("模板定义ID").jdbcType(java.sql.JDBCType.VARCHAR).length(32).commit()
+        .addColumn().name("form_id").alias("formId").comment("表单ID").jdbcType(java.sql.JDBCType.VARCHAR).commit()
+        .addColumn().name("template_id").alias("formTemplateId").comment("前端模板配置").jdbcType(java.sql.JDBCType.VARCHAR).commit()
+        .addColumn().name("permission_dimension").alias("permissionDimension").comment("启动权限配置").jdbcType(java.sql.JDBCType.CLOB).length(32).commit()
+        .addColumn().name("create_time").alias("createTime").comment("创建时间").datetime().commit()
+        .addColumn().name("update_time").alias("updateTime").comment("修改时间").datetime().commit()
+        .addColumn().name("status").alias("status").comment("状态").jdbcType(java.sql.JDBCType.TINYINT).commit()
+        .comment("工作流流程自定义配置")
+        .commit();
+
+    database.createOrAlter("s_wf_act_conf")
+        .addColumn().name("u_id").alias("id").comment("ID").jdbcType(java.sql.JDBCType.VARCHAR).length(32).primaryKey().commit()
+        .addColumn().name("proc_def_key").alias("processDefineKey").comment("模板定义KEY").jdbcType(java.sql.JDBCType.VARCHAR).length(32).commit()
+        .addColumn().name("proc_def_id").alias("processDefineId").comment("模板定义ID").jdbcType(java.sql.JDBCType.VARCHAR).length(32).commit()
+        .addColumn().name("act_id").alias("activityId").comment("元图ID").jdbcType(java.sql.JDBCType.VARCHAR).length(32).commit()
+        .addColumn().name("form_id").alias("formId").comment("表单ID").jdbcType(java.sql.JDBCType.VARCHAR).commit()
+        .addColumn().name("template_id").alias("formTemplateId").comment("前端模板配置").jdbcType(java.sql.JDBCType.VARCHAR).commit()
+        .addColumn().name("candidate_dimension").alias("candidateDimension").comment("候选人维度").jdbcType(java.sql.JDBCType.CLOB).length(32).commit()
+        .addColumn().name("create_time").alias("createTime").comment("创建时间").datetime().commit()
+        .addColumn().name("update_time").alias("updateTime").comment("修改时间").datetime().commit()
+        .addColumn().name("status").alias("status").comment("状态").jdbcType(java.sql.JDBCType.TINYINT).commit()
+        .comment("工作流环节自定义配置")
+        .commit();
+}
+
+//设置依赖
+dependency.setup(info)
+    .onInstall(install)
+    .onUpgrade(function (context) { //更新时执行
+        var upgrader = context.upgrader;
+        upgrader.filter(versions)
+            .upgrade(function (newVer) {
+                newVer.upgrade(context);
+            });
+    })
+    .onUninstall(function (context) { //卸载时执行
+
+    });

+ 55 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/resources/org/hswebframework/web/dao/mybatis/mappers/workflow/ActivityConfigMapper.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://www.mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.hswebframework.web.workflow.dao.ActivityConfigDao">
+    <resultMap id="ActivityConfigResultMap" type="org.hswebframework.web.workflow.dao.entity.ActivityConfigEntity">
+        <id property="id" column="u_id" javaType="string" jdbcType="VARCHAR"/>
+        <result property="activityId" column="act_id" javaType="String" jdbcType="VARCHAR"/>
+        <result property="processDefineKey" column="proc_def_key" javaType="String" jdbcType="VARCHAR"/>
+        <result property="processDefineId" column="proc_def_id" javaType="String" jdbcType="VARCHAR"/>
+        <result property="formId" column="form_id" javaType="String" jdbcType="VARCHAR"/>
+        <result property="formTemplateId" column="template_id" javaType="String" jdbcType="VARCHAR"/>
+        <result property="candidateDimension" column="candidate_dimension" javaType="String" jdbcType="CLOB"/>
+
+        <result property="createTime" column="create_time" javaType="date" jdbcType="TIMESTAMP"/>
+        <result property="updateTime" column="update_time" javaType="date" jdbcType="TIMESTAMP"/>
+        <result property="status" column="status" javaType="Byte" jdbcType="TINYINT"/>
+
+    </resultMap>
+
+    <!--用于动态生成sql所需的配置-->
+    <sql id="config">
+        <bind name="resultMapId" value="'ActivityConfigResultMap'"/>
+        <bind name="tableName" value="'s_wf_act_conf'"/>
+    </sql>
+
+    <insert id="insert" parameterType="org.hswebframework.web.workflow.dao.entity.ActivityConfigEntity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildInsertSql"/>
+    </insert>
+
+    <delete id="deleteByPk" parameterType="String">
+        delete from s_wf_act_conf where u_id =#{id}
+    </delete>
+
+    <delete id="delete" parameterType="org.hswebframework.web.commons.entity.Entity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildDeleteSql"/>
+    </delete>
+
+    <update id="update" parameterType="org.hswebframework.web.commons.entity.Entity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildUpdateSql"/>
+    </update>
+
+    <select id="query" parameterType="org.hswebframework.web.commons.entity.Entity" resultMap="ActivityConfigResultMap">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildSelectSql"/>
+    </select>
+
+    <select id="count" parameterType="org.hswebframework.web.commons.entity.Entity" resultType="int">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildTotalSql"/>
+    </select>
+</mapper>

+ 54 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-local/src/main/resources/org/hswebframework/web/dao/mybatis/mappers/workflow/ProcessDefineConfigMapper.xml

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://www.mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.hswebframework.web.workflow.dao.ProcessDefineConfigDao">
+    <resultMap id="ProcessDefineResultMap" type="org.hswebframework.web.workflow.dao.entity.ProcessDefineConfigEntity">
+        <id property="id" column="u_id" javaType="string" jdbcType="VARCHAR"/>
+        <result property="processDefineKey" column="proc_def_key" javaType="String" jdbcType="VARCHAR"/>
+        <result property="processDefineId" column="proc_def_id" javaType="String" jdbcType="VARCHAR"/>
+        <result property="formId" column="form_id" javaType="String" jdbcType="VARCHAR"/>
+        <result property="formTemplateId" column="template_id" javaType="String" jdbcType="VARCHAR"/>
+        <result property="permissionDimension" column="permission_dimension" javaType="String" jdbcType="CLOB"/>
+
+        <result property="createTime" column="create_time" javaType="date" jdbcType="TIMESTAMP"/>
+        <result property="updateTime" column="update_time" javaType="date" jdbcType="TIMESTAMP"/>
+        <result property="status" column="status" javaType="Byte" jdbcType="TINYINT"/>
+
+    </resultMap>
+
+    <!--用于动态生成sql所需的配置-->
+    <sql id="config">
+        <bind name="resultMapId" value="'ProcessDefineResultMap'"/>
+        <bind name="tableName" value="'s_wf_proc_conf'"/>
+    </sql>
+
+    <insert id="insert" parameterType="org.hswebframework.web.workflow.dao.entity.ProcessDefineConfigEntity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildInsertSql"/>
+    </insert>
+
+    <delete id="deleteByPk" parameterType="String">
+        delete from s_wf_proc_conf where u_id =#{id}
+    </delete>
+
+    <delete id="delete" parameterType="org.hswebframework.web.commons.entity.Entity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildDeleteSql"/>
+    </delete>
+
+    <update id="update" parameterType="org.hswebframework.web.commons.entity.Entity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildUpdateSql"/>
+    </update>
+
+    <select id="query" parameterType="org.hswebframework.web.commons.entity.Entity" resultMap="ProcessDefineResultMap">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildSelectSql"/>
+    </select>
+
+    <select id="count" parameterType="org.hswebframework.web.commons.entity.Entity" resultType="int">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildTotalSql"/>
+    </select>
+</mapper>