diff --git a/ServiceSite/facade/src/main/java/com/seasky/flowportal/api/IBusFlowController.java b/ServiceSite/facade/src/main/java/com/seasky/flowportal/api/IBusFlowController.java
new file mode 100644
index 0000000000000000000000000000000000000000..74333f32327ead18f64304bb0b90addf9338af79
--- /dev/null
+++ b/ServiceSite/facade/src/main/java/com/seasky/flowportal/api/IBusFlowController.java
@@ -0,0 +1,32 @@
+package com.seasky.flowportal.api;
+
+import com.seasky.flowportal.dto.busFlow.BusFlowCmd;
+import com.seasky.flowportal.dto.busFlow.BusFlowOut;
+import com.seasky.flowportal.dto.expenseReimbursement.ExpenseReimbursementOut;
+import com.seasky.flowportal.dto.expenseReimbursement.ExpenseReimbursementQuery;
+import com.seasky.flowportal.dto.flow.FlowQuery;
+import com.seasky.flowportal.dto.flowTool.FlowToolOut;
+import com.seasky.flowportal.dto.response.BaseResultModel;
+import com.seasky.flowportal.dto.todo.TodoOut;
+import com.seasky.flowportal.dto.todo.TodoQuery;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient("seasky-flow-portal")
+@RequestMapping("BusFlow")
+@Api(tags = "busFlow  鑻忚开")
+public interface IBusFlowController {
+
+    @ApiOperation("1.[Q]鏌ヨ鍒楄〃")
+    @PostMapping(path = "/selectBusFlowPo")
+    BaseResultModel<BusFlowOut> selectBusFlow();
+
+    @ApiOperation("閲嶈瘯")
+    @PostMapping(path = "/retryBusFlow")
+    BaseResultModel<Boolean> retryBusFlow(@RequestBody BusFlowCmd busFlowCmd);
+}
diff --git a/ServiceSite/facade/src/main/java/com/seasky/flowportal/dto/busFlow/BusFlowCmd.java b/ServiceSite/facade/src/main/java/com/seasky/flowportal/dto/busFlow/BusFlowCmd.java
new file mode 100644
index 0000000000000000000000000000000000000000..22d054053d4f6887c089aaa459727dd82edb4c81
--- /dev/null
+++ b/ServiceSite/facade/src/main/java/com/seasky/flowportal/dto/busFlow/BusFlowCmd.java
@@ -0,0 +1,49 @@
+package com.seasky.flowportal.dto.busFlow;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+@ApiModel("busflow_dto")
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+public class BusFlowCmd implements Serializable {
+    private Long id;
+
+    private String open;
+
+    private String documentId;
+
+    private String applyCode;
+
+    private String orderStatus;
+
+    private String auditor;
+
+    private String nextOrderStatus;
+
+    private String nextAuditor;
+
+    private Integer executionStatus;
+
+    private String log;
+
+    //瑕佸鐞嗙殑浠诲姟id
+    private String taskBizId;
+
+    //鏄惁瀹℃壒椹冲洖
+    private Boolean isRejected;
+
+    //鏄惁鎹簡鑺傜偣
+    private Boolean isOrderStatusChanged;
+
+    //鍗曟嵁浜嬬敱
+    private String applyReason;
+
+}
diff --git a/ServiceSite/facade/src/main/java/com/seasky/flowportal/dto/busFlow/BusFlowOut.java b/ServiceSite/facade/src/main/java/com/seasky/flowportal/dto/busFlow/BusFlowOut.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8ca0e2098f413a5270f33483e8aee1281ad943d
--- /dev/null
+++ b/ServiceSite/facade/src/main/java/com/seasky/flowportal/dto/busFlow/BusFlowOut.java
@@ -0,0 +1,49 @@
+package com.seasky.flowportal.dto.busFlow;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+@ApiModel("busflow_dto")
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+public class BusFlowOut implements Serializable {
+    private Long id;
+
+    private String open;
+
+    private String documentId;
+
+    private String applyCode;
+
+    private String orderStatus;
+
+    private String auditor;
+
+    private String nextOrderStatus;
+
+    private String nextAuditor;
+
+    private Integer executionStatus;
+
+    private String log;
+
+    //瑕佸鐞嗙殑浠诲姟id
+    private String taskBizId;
+
+    //鏄惁瀹℃壒椹冲洖
+    private Boolean isRejected;
+
+    //鏄惁鎹簡鑺傜偣
+    private Boolean isOrderStatusChanged;
+
+    //鍗曟嵁浜嬬敱
+    private String applyReason;
+
+}
diff --git a/ServiceSite/facade/src/main/java/com/seasky/flowportal/enums/ExecutionStatusEnum.java b/ServiceSite/facade/src/main/java/com/seasky/flowportal/enums/ExecutionStatusEnum.java
new file mode 100644
index 0000000000000000000000000000000000000000..43fbe49c4a6e1dff45c2d78c86ada12e69db8a89
--- /dev/null
+++ b/ServiceSite/facade/src/main/java/com/seasky/flowportal/enums/ExecutionStatusEnum.java
@@ -0,0 +1,31 @@
+package com.seasky.flowportal.enums;
+
+
+public enum ExecutionStatusEnum {
+
+    Unexecuted("鏈墽琛�", 0),
+    Succeeded("宸叉垚鍔�", 1),
+    Retry("寰呴噸璇�", 2),
+    DeletePerson("宸插垹闄よ矗浠讳汉", 3),
+    AdditionalPerson("宸茶拷鍔犺矗浠讳汉",4 );
+    /**
+     * 鏋氫妇灞炴€ц鏄�
+     */
+    private final String name;
+
+    private final int index;
+
+    ExecutionStatusEnum(String name, int index) {
+        this.name = name;
+        this.index = index;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+}
diff --git a/ServiceSite/facade/src/main/java/com/seasky/flowportal/enums/SudiActionEnum.java b/ServiceSite/facade/src/main/java/com/seasky/flowportal/enums/SudiActionEnum.java
new file mode 100644
index 0000000000000000000000000000000000000000..dfcdf3d6ad17b17f7bc6f388a1fc55d4b90eb41f
--- /dev/null
+++ b/ServiceSite/facade/src/main/java/com/seasky/flowportal/enums/SudiActionEnum.java
@@ -0,0 +1,30 @@
+package com.seasky.flowportal.enums;
+
+
+public enum SudiActionEnum {
+
+    FinishTodo("瀹屾垚", 0),
+    CancelTodo("鍙栨秷", 1),
+    CreateTodo("鍒涘缓", 2);
+
+    /**
+     * 鏋氫妇灞炴€ц鏄�
+     */
+    private final String name;
+
+    private final int index;
+
+    SudiActionEnum(String name, int index) {
+        this.name = name;
+        this.index = index;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+}
diff --git a/ServiceSite/facade/src/main/java/com/seasky/flowportal/pojo/BusFlowUserPojo.java b/ServiceSite/facade/src/main/java/com/seasky/flowportal/pojo/BusFlowUserPojo.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e335b58ba04e63fdefa9d2e0da6a5b4960b7fe7
--- /dev/null
+++ b/ServiceSite/facade/src/main/java/com/seasky/flowportal/pojo/BusFlowUserPojo.java
@@ -0,0 +1,26 @@
+package com.seasky.flowportal.pojo;
+
+import com.seasky.core.ddd.base.objects.BaseDto;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author liyulu
+ * @since 2022/1/10
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BusFlowUserPojo extends BaseDto implements Serializable {
+
+    private Long id;
+
+    private String userNo;
+
+    private String userName;
+}
diff --git a/ServiceSite/pom.xml b/ServiceSite/pom.xml
index 0109ba9c7520ea2eae8b2bfbacaa023a5445fb8c..c120b0c72c8189738dce31f7f5a3212be61af18f 100644
--- a/ServiceSite/pom.xml
+++ b/ServiceSite/pom.xml
@@ -199,6 +199,11 @@
             <version>2.4.10</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/controller/BusFlowController.java b/ServiceSite/src/main/java/com/seasky/flowportal/controller/BusFlowController.java
new file mode 100644
index 0000000000000000000000000000000000000000..88c880fee33aa298f1b94d5792d472157377d48e
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/controller/BusFlowController.java
@@ -0,0 +1,42 @@
+package com.seasky.flowportal.controller;
+
+
+import com.seasky.flowportal.api.IBusFlowController;
+import com.seasky.flowportal.api.IMyFlowController;
+import com.seasky.flowportal.domain.po.BusFlowPo;
+import com.seasky.flowportal.dto.busFlow.BusFlowCmd;
+import com.seasky.flowportal.dto.busFlow.BusFlowOut;
+import com.seasky.flowportal.dto.expenseReimbursement.ExpenseReimbursementOut;
+import com.seasky.flowportal.dto.expenseReimbursement.ExpenseReimbursementQuery;
+import com.seasky.flowportal.dto.flow.FlowQuery;
+import com.seasky.flowportal.dto.flowTool.FlowToolOut;
+import com.seasky.flowportal.dto.response.BaseResultModel;
+import com.seasky.flowportal.dto.todo.TodoOut;
+import com.seasky.flowportal.dto.todo.TodoQuery;
+import com.seasky.flowportal.dto.user.UserInfoOut;
+import com.seasky.flowportal.enums.FlowQueryEnum;
+import com.seasky.flowportal.enums.PortalResponseCode;
+import com.seasky.flowportal.service.BusFlowService;
+import com.seasky.flowportal.service.ExpenseReimbursementService;
+import com.seasky.flowportal.service.FlowService;
+import com.seasky.flowportal.service.LoginPortalService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RestController;
+
+import static com.seasky.flowportal.dto.response.PortalResponse.ok;
+
+@RestController
+public class BusFlowController implements IBusFlowController {
+    @Autowired
+    private BusFlowService busFlowService;
+
+    @Override
+    public BaseResultModel<BusFlowOut> selectBusFlow() {
+        return ok(PortalResponseCode.SUCCESS, busFlowService.selectBusFlow());
+    }
+
+    @Override
+    public BaseResultModel<Boolean> retryBusFlow(BusFlowCmd busFlowCmd) {
+        return ok(PortalResponseCode.SUCCESS, busFlowService.retryBusFlow(busFlowCmd));
+    }
+}
\ No newline at end of file
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/controller/MenuController.java b/ServiceSite/src/main/java/com/seasky/flowportal/controller/MenuController.java
index 3a15c53ed8e7097d951d4e21974f5cb4c050b147..85f0bceded8121e2b33cbe21dba2cf02e32a6a41 100644
--- a/ServiceSite/src/main/java/com/seasky/flowportal/controller/MenuController.java
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/controller/MenuController.java
@@ -38,6 +38,7 @@ public class MenuController {
     @PostMapping(path = "ResetBaseConfig")
     @ApiOperation("閲嶇疆BaseData閰嶇疆")
     BaseResultModel<BaseConfigProperties> resetBaseConfig() {
+        RedisUtil.getRedisCommand().del("BaseConfigProperties");
         //娓呴櫎閰嶇疆缂撳瓨
         RedisUtil.getRedisCommand().del("BaseConfigProperties");
        /* Object baseConfigProperties = RedisUtil.getRedisCommand().get("BaseConfigProperties");
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/ApplicationVO.java b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/ApplicationVO.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3e838f41e30be0a469f8e7d356f8858e55017ff
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/ApplicationVO.java
@@ -0,0 +1,44 @@
+package com.seasky.flowportal.domain.po;
+
+/**
+ *鐢ㄦ埛淇℃伅
+ */
+public class ApplicationVO {
+
+    private int id;
+    private String name;
+    private String code;
+    private String secretKey;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getSecretKey() {
+        return secretKey;
+    }
+
+    public void setSecretKey(String secretKey) {
+        this.secretKey = secretKey;
+    }
+}
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/BusFlowPo.java b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/BusFlowPo.java
new file mode 100644
index 0000000000000000000000000000000000000000..116b468e8e4858db89e1df7303f46a01b105396b
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/BusFlowPo.java
@@ -0,0 +1,46 @@
+package com.seasky.flowportal.domain.po;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.sun.xml.internal.ws.developer.Serialization;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Serialization
+@TableName(value = "tb_bus_flow",autoResultMap = true)
+public class BusFlowPo extends BasePO{
+
+    @TableField(value = "open")
+    private String open;
+
+    @TableField(value = "document_id")
+    private String documentId;
+
+    @TableField(value = "apply_code")
+    private String applyCode;
+
+    @TableField(value = "order_status")
+    private String orderStatus;
+
+    @TableField(value = "auditor")
+    private String auditor;
+
+    @TableField(value = "next_order_status")
+    private String nextOrderStatus;
+
+    @TableField(value = "next_auditor")
+    private String nextAuditor;
+
+    @TableField(value = "execution_status")
+    private Integer executionStatus;
+
+    @TableField(value = "log")
+    private String log;
+}
\ No newline at end of file
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/BusFlowUserModel.java b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/BusFlowUserModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a44a5bf751bea4637cbf666c9a231aee8348ee9
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/BusFlowUserModel.java
@@ -0,0 +1,28 @@
+package com.seasky.flowportal.domain.po;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 
+ * @author   liyulu
+ * @date   2022-01-04
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BusFlowUserModel extends BasePO {
+
+    private String userId;
+
+    private String userCode;
+
+    private String userName;
+
+    private Integer executionStatus;
+}
\ No newline at end of file
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/FinishTaskVO.java b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/FinishTaskVO.java
new file mode 100644
index 0000000000000000000000000000000000000000..53907ee268a3cf826abdf7c86d5346f506b775ab
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/FinishTaskVO.java
@@ -0,0 +1,19 @@
+package com.seasky.flowportal.domain.po;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class FinishTaskVO extends BasePO {
+
+    private Date doneDate;
+
+}
\ No newline at end of file
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/ParticipantVO.java b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/ParticipantVO.java
new file mode 100644
index 0000000000000000000000000000000000000000..03cccfeb9292f8f04d0f6421fc38d1aaf102b2d9
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/ParticipantVO.java
@@ -0,0 +1,108 @@
+package com.seasky.flowportal.domain.po;
+
+
+/**
+* 浠诲姟鐨勫弬涓庤€咃紝鍗宠矗浠讳汉.姝ょ被涓哄熀绫伙紝鍏朵箣绫绘湁锛氱敤鎴峰弬涓庤€咃紙鍗充汉鍛橈級锛屾満鏋勫弬涓庤€咃紙鍗硂rg锛夛紝缁勫弬涓庤€咃紙鍗冲叏灞€缁勶級
+*/
+public class ParticipantVO {
+	/** */
+	public static final int TYPE_USER = 0;
+	/** */
+	public static final int TYPE_ORG = 1;
+	/** */
+	public static final int TYPE_GROUP = 2;
+
+	
+	/** */
+	private int id;
+	/**缁勫弬涓庤€呫€倀ype=TYPE_GROUP鏃舵湁鏁� */
+	private String groupName;
+	/**type=TYPE_ORG鏃讹紝鏈烘瀯鏄惁閫掑綊 */
+	private boolean recursiveOrg;
+	/**鍙備笌鑰呯被鍨�,鏈塗YPE_USER(0)锛孴YPE_ORG(1)锛孴YPE_GROUP(2) */
+	private int type;
+	/**浜哄憳鍙備笌鑰呫€倀ype=TYPE_USER鏃舵湁鏁堛€傛鍊煎繀椤绘槸鏍℃柟鏁版嵁涓績鍏竷鐨勫敮涓€浜哄憳id锛岄€氬父鏄宸ュ彿銆� */
+	private String userCode;
+	/**鏈烘瀯鍙備笌鑰呫€倀ype=TYPE_ORG鏈夋晥 銆傛鍊煎繀椤绘槸鏍℃柟鏁版嵁涓績鍏竷鐨勫敮涓€缁勭粐鏈烘瀯浠g爜銆�*/
+	private String orgCode;
+
+	/**濮旀墭鑰呯被鍨�,鏈塂ELEGATETYPE_COMMON锛孌ELEGATETYPE_FROM锛孌ELEGATETYPE_TO */
+	private boolean delegate;
+	/**濮旀墭鎻忚堪銆傚鎵樿€呯被鍨嬮潪common鏃剁敓鏁� */
+	private String delegateLoginName;
+
+	private String delegateName;
+
+	/**鏄惁鐩戠潱浜�*/
+	private boolean monitor;
+
+
+	public boolean isDelegate() {
+		return delegate;
+	}
+
+	public void setDelegate(boolean delegate) {
+		this.delegate = delegate;
+	}
+
+	public String getDelegateLoginName() {
+		return delegateLoginName;
+	}
+
+	public void setDelegateLoginName(String delegateLoginName) {
+		this.delegateLoginName = delegateLoginName;
+	}
+
+	public String getDelegateName() {
+		return delegateName;
+	}
+
+	public void setDelegateName(String delegateName) {
+		this.delegateName = delegateName;
+	}
+
+	public int getId() {
+		return id;
+	}
+	public void setId(int id) {
+		this.id = id;
+	}
+	public String getGroupName() {
+		return groupName;
+	}
+	public void setGroupName(String groupName) {
+		this.groupName = groupName;
+	}
+	public boolean isRecursiveOrg() {
+		return recursiveOrg;
+	}
+	public void setRecursiveOrg(boolean recursiveOrg) {
+		this.recursiveOrg = recursiveOrg;
+	}
+	public int getType() {
+		return type;
+	}
+	public void setType(int type) {
+		this.type = type;
+	}
+	public String getUserCode() {
+		return userCode;
+	}
+	public void setUserCode(String userCode) {
+		this.userCode = userCode;
+	}
+	public String getOrgCode() {
+		return orgCode;
+	}
+	public void setOrgCode(String orgCode) {
+		this.orgCode = orgCode;
+	}
+
+	public boolean isMonitor() {
+		return monitor;
+	}
+
+	public void setMonitor(boolean monitor) {
+		this.monitor = monitor;
+	}
+}
\ No newline at end of file
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/TaskAndDoneAO.java b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/TaskAndDoneAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..26923b47919e3abeacbb423cd6aece83154329ef
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/TaskAndDoneAO.java
@@ -0,0 +1,31 @@
+package com.seasky.flowportal.domain.po;
+
+/**
+ * 鍒涘缓骞跺畬鎴愬璞�
+ */
+public class TaskAndDoneAO {
+    /**
+     * 浠诲姟瀵硅薄
+     */
+    private TaskVO taskVO;
+    /**
+     * 瀹屾垚瀵硅薄
+     */
+    private UserDoneAO userDoneAO;
+
+    public TaskVO getTaskVO() {
+        return taskVO;
+    }
+
+    public void setTaskVO(TaskVO taskVO) {
+        this.taskVO = taskVO;
+    }
+
+    public UserDoneAO getUserDoneAO() {
+        return userDoneAO;
+    }
+
+    public void setUserDoneAO(UserDoneAO userDoneAO) {
+        this.userDoneAO = userDoneAO;
+    }
+}
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/TaskVO.java b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/TaskVO.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc956e4734d6a7c789ed52053932e013a1ba0a49
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/TaskVO.java
@@ -0,0 +1,385 @@
+package com.seasky.flowportal.domain.po;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+
+/**
+* 浠诲姟
+*/
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class TaskVO {
+
+	/**浠诲姟绱ф€ュ害锛氫綆 */
+	public static final int URGENT_LOW = 0;
+	/**浠诲姟绱ф€ュ害锛氫腑 */
+	public static final int URGENT_MIDDLE = 1;
+	/**浠诲姟绱ф€ュ害锛氶珮 */
+	public static final int URGENT_HIGH = 2;
+	/**浠诲姟绱ф€ュ害锛氱揣鎬� */
+	public static final int URGENT_HIGHEST = 3;
+	/**浠诲姟閲嶈绋嬪害锛氫綆 */
+	public static final int IMPORTANCE_LOW = 0;
+	/**浠诲姟閲嶈绋嬪害锛氫腑 */
+	public static final int IMPORTANCE_MIDDLE = 1;
+	/**浠诲姟閲嶈绋嬪害锛氶珮 */
+	public static final int IMPORTANCE_HIGH = 2;
+	/**浠诲姟閲嶈绋嬪害锛氬強鍏堕噸瑕� */
+	public static final int IMPORTANCE_HIGHEST = 3;
+	/**浠诲姟鐘舵€侊細鏈畬鎴� */
+	public static final int STATE_UNDO = 0;
+	/**浠诲姟鐘舵€侊細宸插畬鎴� */
+	public static final int STATE_DONE = 1;
+	/**浠诲姟鐘舵€侊細鍙栨秷 */
+	public static final int STATE_CANCELED = -1;
+	
+	
+	/** */
+	private int id;
+	/**闄勪欢灞炴€�1 */
+	private String tag1;
+	/**浠诲姟鐨勪笟鍔d銆傛id鏈塧pp缁欏嚭锛宎pp闇€瑕佽嚜宸变繚璇佸叾鍞竴鎬с€傜敤浜巃pp瀵逛换鍔¤繘琛屾搷浣� */
+	private String taskBizId;
+	/**浠诲姟琚挙閿€鏃剁殑鏃堕棿 */
+	private Date cancelDate;
+	/**閲嶈绋嬪害锛屽弬瑙佸父閲廔MPORTANCE_LOW,IMPORTANCE_MIDDLE,IMPORTANCE_HIGH,IMPORTANCE_HIGHEST */
+	private int importance;
+	/**鏉冮噸銆傛涓鸿嚜鍔ㄨ绠楀瓧娈点€傚叾鍊间负urgent+importance */
+	private int weight;
+	/**浠诲姟鏍囬 */
+	private String title;
+	/**瑕佹眰瀹屾垚鏃堕棿 */
+	private Date deadLine;
+	/**浠诲姟鐨勫鐞唘rl */
+	private String url;
+	/**闄勪欢灞炴€�2 */
+	private String tag2;
+	/**闄勪欢灞炴€�3 */
+	private String tag3;
+	/**浠诲姟鍓爣棰� */
+	private String subTitle;
+	/**浠诲姟鍒涘缓鏃堕棿銆俛pp鍒涘缓task鏃讹紝濡傛灉娌℃湁鎸囧畾createTime锛岀郴缁熷皢閲囩敤褰撳墠鏃堕棿浣滀负createTime */
+	private Date createTime;
+	/**浠诲姟瀹屾垚鏃堕棿 */
+	private Date doneTime;
+	/**浠诲姟鐘舵€�.鍙傝甯搁噺STATE_UNDO,STATE_DONE,STATE_CANCELED */
+	private int state;
+	/**浠诲姟绱ф€ョ▼搴︺€傚弬瑙佸父閲� URGENT_LOW,URGENT_MIDDLE,URGENT_HIGH, URGENT_HIGHEST */
+	private int urgent;
+	/**浠诲姟鏉ユ簮*/
+	private String source;
+	/**
+	 * 浠诲姟鍒涘缓鑰呯殑浠g爜锛岀敱鏍℃柟鏁版嵁涓績缁欏嚭锛岄€氬父涓鸿亴宸ュ彿
+	 */
+	private String creatorId;
+	/**
+	 * 鍒涘缓浜哄鍚�
+	 */
+	private String createName;
+
+	/**浠诲姟鐨勫凡鍔瀠rl */
+	private String doneUrl;
+
+	/**
+	 * 鐖朵换鍔askBizId锛岀埗浠诲姟鍜屽瓙浠诲姟灞炰簬鍚屼竴涓猘pp
+	 */
+
+	private String parentTaskBizId;
+
+	/**
+	 * parentTask鐖朵换鍔�
+	 */
+
+	private TaskVO parentTask;
+
+	/**鏄惁鏄祦绋嬭窡韪换鍔� 涔嬪墠鐗堟湰浣跨敤tag1=proc瀛樺偍 */
+	private boolean processTrace;
+
+	/**
+	 * 鎺掑簭
+	 */
+	private int sort = 50;
+
+	/**
+	 * 鏄惁涓嶆樉绀� 榛樿false鏄剧ず
+	 */
+	private boolean notShow = false;
+
+
+	/**
+	 * 娴佺▼璺熻釜鎴戠殑鐢宠浠诲姟褰撳墠鑺傜偣鍚嶇О
+	 */
+
+	private String processCurrentTask;
+
+	/**
+	 * 璁″垝寮€濮嬫椂闂�
+	 */
+	private Date planStartTime;
+
+	private String handler;
+
+	private boolean monitor;
+	private boolean deadSearch;
+	public String getParentTaskBizId() {
+		return parentTaskBizId;
+	}
+
+	public int getSort() {
+		return sort;
+	}
+
+	public void setSort(int sort) {
+		this.sort = sort;
+	}
+
+	public boolean isNotShow() {
+		return notShow;
+	}
+
+	public void setNotShow(boolean notShow) {
+		this.notShow = notShow;
+	}
+
+	public void setParentTaskBizId(String parentTaskBizId) {
+		this.parentTaskBizId = parentTaskBizId;
+	}
+
+	public String getProcessCurrentTask() {
+		return processCurrentTask;
+	}
+
+	public void setProcessCurrentTask(String processCurrentTask) {
+		this.processCurrentTask = processCurrentTask;
+	}
+
+	public String getDoneUrl() {
+		return doneUrl;
+	}
+
+	public void setDoneUrl(String doneUrl) {
+		this.doneUrl = doneUrl;
+	}
+
+	public boolean isProcessTrace() {
+		return processTrace;
+	}
+
+	public void setProcessTrace(boolean processTrace) {
+		this.processTrace = processTrace;
+	}
+
+	/**
+	 * 鍙備笌鑰�
+	 */
+	private ParticipantVO[] participants;
+
+	public int getId() {
+		return id;
+	}
+
+	public void setId(int id) {
+		this.id = id;
+	}
+
+	public String getTag1() {
+		return tag1;
+	}
+
+	public void setTag1(String tag1) {
+		this.tag1 = tag1;
+	}
+
+	public String getTaskBizId() {
+		return taskBizId;
+	}
+
+	public void setTaskBizId(String taskBizId) {
+		this.taskBizId = taskBizId;
+	}
+
+	public Date getCancelDate() {
+		return cancelDate;
+	}
+
+	public void setCancelDate(Date cancelDate) {
+		this.cancelDate = cancelDate;
+	}
+
+	public int getImportance() {
+		return importance;
+	}
+
+	public void setImportance(int importance) {
+		this.importance = importance;
+	}
+
+	public int getWeight() {
+		return weight;
+	}
+
+	public void setWeight(int weight) {
+		this.weight = weight;
+	}
+
+	public String getTitle() {
+		return title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public Date getDeadLine() {
+		return deadLine;
+	}
+
+	public void setDeadLine(Date deadLine) {
+		this.deadLine = deadLine;
+	}
+
+	public String getUrl() {
+		return url;
+	}
+
+	public void setUrl(String url) {
+		this.url = url;
+	}
+
+	public String getTag2() {
+		return tag2;
+	}
+
+	public void setTag2(String tag2) {
+		this.tag2 = tag2;
+	}
+
+	public String getTag3() {
+		return tag3;
+	}
+
+	public void setTag3(String tag3) {
+		this.tag3 = tag3;
+	}
+
+	public String getSubTitle() {
+		return subTitle;
+	}
+
+	public void setSubTitle(String subTitle) {
+		this.subTitle = subTitle;
+	}
+
+	public Date getCreateTime() {
+		return createTime;
+	}
+
+	public void setCreateTime(Date createTime) {
+		this.createTime = createTime;
+	}
+
+	public Date getDoneTime() {
+		return doneTime;
+	}
+
+	public void setDoneTime(Date doneTime) {
+		this.doneTime = doneTime;
+	}
+
+	public int getState() {
+		return state;
+	}
+
+	public void setState(int state) {
+		this.state = state;
+	}
+
+	public int getUrgent() {
+		return urgent;
+	}
+
+	public void setUrgent(int urgent) {
+		this.urgent = urgent;
+	}
+
+	public String getCreatorId() {
+		return creatorId;
+	}
+
+	public void setCreatorId(String creatorId) {
+		this.creatorId = creatorId;
+	}
+
+	public ParticipantVO[] getParticipants() {
+		return participants;
+	}
+
+	public void setParticipants(ParticipantVO[] participants) {
+		this.participants = participants;
+	}
+
+	public String getSource() {
+		return source;
+	}
+
+	public void setSource(String source) {
+		this.source = source;
+	}
+
+	public String getCreateName() {
+		return createName;
+	}
+
+	public void setCreateName(String createName) {
+		this.createName = createName;
+	}
+
+	public TaskVO getParentTask() {
+		return parentTask;
+	}
+
+	public void setParentTask(TaskVO parentTask) {
+		this.parentTask = parentTask;
+	}
+
+	public Date getPlanStartTime() {
+		return planStartTime;
+	}
+
+	public void setPlanStartTime(Date planStartTime) {
+		this.planStartTime = planStartTime;
+	}
+
+	public String getHandler() {
+		return handler;
+	}
+
+	public void setHandler(String handler) {
+		this.handler = handler;
+	}
+
+	public boolean isMonitor() {
+		return monitor;
+	}
+
+	public void setMonitor(boolean monitor) {
+		this.monitor = monitor;
+	}
+
+	public boolean isDeadSearch() {
+		return deadSearch;
+	}
+
+	public void setDeadSearch(boolean deadSearch) {
+		this.deadSearch = deadSearch;
+	}
+}
\ No newline at end of file
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/UserDoneAO.java b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/UserDoneAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..73da7168305736b548d8ead448cdaf4b047321a2
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/domain/po/UserDoneAO.java
@@ -0,0 +1,77 @@
+package com.seasky.flowportal.domain.po;
+
+import java.util.Date;
+
+/**
+ * 鐢ㄦ埛瀵硅薄
+ */
+public class UserDoneAO {
+	/**
+	 * 瀹屾垚鏃堕棿銆傚鏋滀笉浼犻€掓鍙傛暟锛屽皢浣跨敤绯荤粺褰撳墠鏃堕棿浣滀负鍏跺畬鎴愭椂闂�
+	 */
+	private Date doneDate;
+	/**
+	 * 浠诲姟涓績鐨勪繚鐣欏弬鏁帮紝涓嶉渶瑕佷紶閫掋€�
+	 */
+	private String extraUserGroup;
+	/**
+	 * 鏄惁鍚屾椂finish鏁翠釜浠诲姟銆�
+	 */
+	private boolean finishTask;
+
+	/**
+	 * 鏄惁濮旀墭
+	 */
+	private boolean delegate;
+	/**
+	 * 濮旀墭浜篖oginName
+	 */
+	private String delegateLoginName;
+	/**
+	 * 濮旀墭浜篘ame
+	 */
+	private String delegateName;
+
+	public boolean isDelegate() {
+		return delegate;
+	}
+
+	public void setDelegate(boolean delegate) {
+		this.delegate = delegate;
+	}
+
+	public String getDelegateLoginName() {
+		return delegateLoginName;
+	}
+
+	public void setDelegateLoginName(String delegateLoginName) {
+		this.delegateLoginName = delegateLoginName;
+	}
+
+	public String getDelegateName() {
+		return delegateName;
+	}
+
+	public void setDelegateName(String delegateName) {
+		this.delegateName = delegateName;
+	}
+
+	public Date getDoneDate() {
+		return doneDate;
+	}
+	public void setDoneDate(Date doneDate) {
+		this.doneDate = doneDate;
+	}
+	public String getExtraUserGroup() {
+		return extraUserGroup;
+	}
+	public void setExtraUserGroup(String extraUserGroup) {
+		this.extraUserGroup = extraUserGroup;
+	}
+	public boolean isFinishTask() {
+		return finishTask;
+	}
+	public void setFinishTask(boolean finishTask) {
+		this.finishTask = finishTask;
+	}
+}
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/mapper/BusFlowMapper.java b/ServiceSite/src/main/java/com/seasky/flowportal/mapper/BusFlowMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..daebeff54a61b258a61e73752f3fef4c35c961df
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/mapper/BusFlowMapper.java
@@ -0,0 +1,15 @@
+package com.seasky.flowportal.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.seasky.flowportal.domain.po.BusFlowPo;
+import com.seasky.flowportal.domain.po.History;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface BusFlowMapper extends BaseMapper<BusFlowPo> {
+    List<BusFlowPo> selectListByEx();
+
+    BusFlowPo selectFirstNotYetSSuccessfulBusFlow();
+}
\ No newline at end of file
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/mapper/xml/BusFlowMapper.xml b/ServiceSite/src/main/java/com/seasky/flowportal/mapper/xml/BusFlowMapper.xml
new file mode 100644
index 0000000000000000000000000000000000000000..829768ab8d2287b95d9e0b9873ed911d38f48f9b
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/mapper/xml/BusFlowMapper.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.seasky.flowportal.mapper.BusFlowMapper">
+    <select id="selectListByEx"
+            resultType="com.seasky.flowportal.domain.po.BusFlowPo">
+        select *
+        from (
+                 select *,row_number() over (partition by apply_code order by create_date) as group_idx
+                 from tb_bus_flow
+             ) u
+        where u.group_idx = 1 and execution_status = 2
+        order by create_date asc
+    </select>
+</mapper>`
\ No newline at end of file
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/service/BusFlowService.java b/ServiceSite/src/main/java/com/seasky/flowportal/service/BusFlowService.java
new file mode 100644
index 0000000000000000000000000000000000000000..2bf9adc1c8f75051d31d259110965e26a3568217
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/service/BusFlowService.java
@@ -0,0 +1,17 @@
+package com.seasky.flowportal.service;
+
+import com.seasky.flowportal.domain.po.BusFlowPo;
+import com.seasky.flowportal.dto.busFlow.BusFlowCmd;
+import com.seasky.flowportal.dto.busFlow.BusFlowOut;
+
+import java.util.List;
+
+public interface BusFlowService {
+    List<BusFlowOut> selectBusFlow();
+
+    boolean retryBusFlow(BusFlowCmd busFlowCmd);
+
+    void createAndPushBusFlow(BusFlowPo busFlowPo);
+
+    /*void sendBusFlow();*/
+}
\ No newline at end of file
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/service/convert/BusFlowConvert.java b/ServiceSite/src/main/java/com/seasky/flowportal/service/convert/BusFlowConvert.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ceeb869869f7f83f05f7c98b3973760b2f33fe3
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/service/convert/BusFlowConvert.java
@@ -0,0 +1,34 @@
+package com.seasky.flowportal.service.convert;
+
+import com.seasky.core.ddd.utils.MapperUtils;
+import com.seasky.flowportal.domain.po.BusFlowPo;
+import com.seasky.flowportal.dto.busFlow.BusFlowCmd;
+import com.seasky.flowportal.dto.busFlow.BusFlowOut;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class BusFlowConvert {
+
+    public static BusFlowPo cmdToPo(BusFlowCmd busFlowCmd) {
+        //杞崲瀵瑰簲閿€糾ap
+        Map<String, String> map = new HashMap<>(3);
+        BusFlowPo busFlowPo = MapperUtils.INSTANCE.map(BusFlowPo.class, busFlowCmd);
+        return busFlowPo;
+    }
+
+    public static BusFlowCmd poToCmd(BusFlowPo busFlowPo) {
+        //杞崲瀵瑰簲閿€糾ap
+        Map<String, String> map = new HashMap<>(3);
+        BusFlowCmd busFlowCmd = MapperUtils.INSTANCE.map(BusFlowCmd.class, busFlowPo);
+        return busFlowCmd;
+    }
+
+    public static List<BusFlowOut> listPoToOut(List<BusFlowPo> busFlowPoList) {
+        //杞崲瀵瑰簲閿€糾ap
+        Map<String, String> map = new HashMap<>(3);
+        List<BusFlowOut> busFlowOutList = MapperUtils.INSTANCE.mapAsList(BusFlowOut.class, busFlowPoList);
+        return busFlowOutList;
+    }
+}
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/BusFlowServiceImpl.java b/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/BusFlowServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..909b78fd28b174d1c8a42189146df2601092b2d6
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/BusFlowServiceImpl.java
@@ -0,0 +1,748 @@
+package com.seasky.flowportal.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.seasky.core.common.ResponseCode;
+import com.seasky.core.util.ExceptionUtil;
+import com.seasky.flowportal.domain.po.*;
+import com.seasky.flowportal.dto.busFlow.BusFlowCmd;
+import com.seasky.flowportal.dto.busFlow.BusFlowOut;
+import com.seasky.flowportal.dto.response.BaseResultModel;
+import com.seasky.flowportal.dto.response.SuccessResultModel;
+import com.seasky.flowportal.enums.ExecutionStatusEnum;
+import com.seasky.flowportal.enums.OpenEnum;
+import com.seasky.flowportal.enums.OrderStatusEnum;
+import com.seasky.flowportal.enums.SudiActionEnum;
+import com.seasky.flowportal.mapper.BusFlowMapper;
+import com.seasky.flowportal.mapper.ExpenseReimbursementMapper;
+import com.seasky.flowportal.service.BusFlowService;
+import com.seasky.flowportal.service.LoginPortalService;
+import com.seasky.flowportal.service.convert.BusFlowConvert;
+import com.seasky.flowportal.utils.MyHttpDelete;
+import com.seasky.flowportal.utils.SudySignUtil;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+/**
+ * @program:
+ * @author: kejinlong
+ * @create: 2022-08-17 16:57
+ **/
+@Service
+@RabbitListener(queues = "bus_flow")
+public class BusFlowServiceImpl implements BusFlowService {
+
+    @Autowired
+    private BusFlowMapper busFlowMapper;
+
+    @Autowired
+    private AmqpTemplate amqpTemplate;
+
+    @Value("${algorithm}")
+    public String algorithm;
+
+    @Value("${appCode}")
+    public String appCode;
+
+    @Value("${taskCategoryCode}")
+    public String taskCategoryCode;
+
+    @Value("${secret}")
+    public String secret;
+
+    @Value("${Host}")
+    public String Host;
+
+    @Value("${SendTimes}")
+    public String SendTimes;
+
+
+    @Autowired
+    private LoginPortalService loginPortalService;
+
+    @Autowired
+    private ExpenseReimbursementMapper expenseReimbursementMapper;
+
+    @Override
+    public void createAndPushBusFlow(BusFlowPo busFlowPo) {
+        Integer integer = saveBusFlow(busFlowPo);
+        if (integer != 1) {
+            saveBusFlow(busFlowPo);
+        }
+    }
+
+    @Override
+    public List<BusFlowOut> selectBusFlow() {
+        List<BusFlowPo> busFlowPoList = busFlowMapper.selectListByEx();
+        List<BusFlowOut> busFlowOutList = BusFlowConvert.listPoToOut(busFlowPoList);
+        return busFlowOutList;
+    }
+
+    // 鎺ュ彛璋冪敤鎿嶄綔閲嶈瘯
+    @Override
+    @Retryable
+    public boolean retryBusFlow(BusFlowCmd busFlowCmd) {
+        BusFlowPo busFlowPo = BusFlowConvert.cmdToPo(busFlowCmd);
+        //椤甸潰涓婂睍绀烘帴鍙h皟鐢ㄦ搷浣滀负ExecutionStatus = 2銆佹煇涓崟鍙风殑鏈€鏃╀竴涓搷浣滐紝
+        // 姣忎釜鎿嶄綔鍚庢湁涓噸璇曟寜閽紝鐐瑰嚮鎿嶄綔A鐨勯噸璇曟寜閽悗A.ExecutionStatus = 0骞朵繚瀛橈紝灏咥.ApplyCode鍏ラ槦銆傛垚鍔熷悗鎸夐挳鎻愮ず宸叉垚鍔熴€�
+        if (ExecutionStatusEnum.Retry.getIndex() != busFlowPo.getExecutionStatus()) {
+            ExceptionUtil.getException(null, "鏁版嵁涓嶆纭� 璇烽噸鏂伴€夋嫨");
+        }
+        busFlowPo.setExecutionStatus(ExecutionStatusEnum.Unexecuted.getIndex());
+        Integer result = saveBusFlow(busFlowPo);
+        if (result > 1) {
+            return true;
+        }
+        return false;
+    }
+
+    //淇濆瓨鎺ュ彛淇℃伅
+    public Integer saveBusFlow(BusFlowPo busFlowPo) {
+        //娴佺▼涓績鎻掑叆涓€鏉¤褰曡嚦鏁版嵁搴撲腑鐨勫悓鏃讹紝灏嗚繖涓� id  鍏ラ槦
+        int insert = busFlowMapper.insert(busFlowPo);
+        String id = busFlowPo.getApplyCode();
+        amqpTemplate.convertAndSend("bus_flow", id);
+        return insert;
+    }
+
+
+
+    @RabbitListener(queues = "bus_flow")
+    @RabbitHandler
+    public void start(String applyCode){
+        if (ObjectUtils.isEmpty(applyCode)){
+            ExceptionUtil.getException(null,"闃熷垪鏃犳暟鎹�");
+        }
+        List<BusFlowPo> busFlowPoList = busFlowMapper.selectList(new QueryWrapper<BusFlowPo>().eq("apply_code", applyCode).orderByDesc("create_date"));
+        if (ObjectUtils.isNotEmpty(busFlowPoList)){
+            BusFlowPo busFlowPo = busFlowPoList.get(0);
+            if (ObjectUtils.isNotEmpty(busFlowPo)){
+                executeBusFlow(busFlowPo);
+            }
+        }
+        //==================
+/*        List<BusFlowPo> busFlowPoList1 = busFlowMapper.selectList(new QueryWrapper<BusFlowPo>().ne("execution_status", 1).orderByAsc("create_date"));
+        BusFlowPo busFlowPo = busFlowPoList1.get(0);
+        if (ObjectUtils.isEmpty(busFlowPo) || busFlowPo.getExecutionStatus() == ExecutionStatusEnum.Retry.getIndex()){
+            //
+        }
+        if (busFlowPo.getExecutionStatus() == ExecutionStatusEnum.Unexecuted.getIndex()){
+            boolean flag = (busFlowPo.getOpen().equals(OpenEnum.CREATE.getName()) || busFlowPo.getOrderStatus().equals("瀹屾垚"));
+            if (ObjectUtils.isEmpty(busFlowPo.getAuditor()) && !flag){
+                ExceptionUtil.getException(null,"瀹℃牳浜轰笉鑳戒负绌�");
+            }
+            boolean flag1 = (busFlowPo.getNextOrderStatus().equals("瀹℃壒椹冲洖") || busFlowPo.getNextOrderStatus().equals("瀹屾垚"));
+            if (ObjectUtils.isEmpty(busFlowPo.getNextAuditor()) || busFlowPo.getNextAuditor().split(",").length == 0 && !flag1){
+                ExceptionUtil.getException(null,"寰呭姙浜轰笉鑳戒负绌�");
+            }
+            executeBusFlow(busFlowPo);
+        }
+        List<BusFlowPo> busFlowPoList2 = busFlowMapper.selectList(new QueryWrapper<BusFlowPo>().ne("execution_status", 1).orderByAsc("create_date"));
+        BusFlowPo busFlowPo1 = busFlowPoList2.get(0);
+        if (busFlowPo1.getExecutionStatus().equals(ExecutionStatusEnum.Unexecuted.getIndex())){
+            saveBusFlow(busFlowPo1);
+        }*/
+    }
+
+    public boolean executeBusFlow(BusFlowPo busFlowPo1) {
+        BusFlowCmd busFlowCmd = BusFlowConvert.poToCmd(busFlowPo1);
+        Boolean isRejected = busFlowCmd.getOpen() == OpenEnum.BACK.getName() || (busFlowCmd.getOpen() == OpenEnum.REVOKE.getName() && busFlowCmd.getNextOrderStatus() == OrderStatusEnum.APPLY.getName());
+        Boolean isOrderStatusChanged = busFlowCmd.getOrderStatus() != busFlowCmd.getNextOrderStatus();
+        busFlowCmd.setIsRejected(isRejected);
+        busFlowCmd.setIsOrderStatusChanged(isOrderStatusChanged);
+        BaseResultModel<Boolean> result = new SuccessResultModel<>();
+        OpenEnum openEnum = OpenEnum.getValueByIndex(busFlowCmd.getOpen());
+        //鍏堝鐞嗗凡鏈夊緟鍔烇紝濡傛灉鏈夊鏍歌妭鐐广€佸鏍镐汉锛孫pen = 鈥淩evoke鈥濇椂鎵ц2.2.8锛孫pen = 鈥淪ubmit鈥濇垨Open = 鈥淏ack鈥濇椂鎵ц2.2.10銆傚啀娣诲姞鏂板緟鍔烇紝濡傛灉鏈夊緟鍔炶妭鐐广€佸緟鍔炰汉锛屼负姣忎釜寰呭姙浜哄厛鎵ц2.2.8鍐嶆墽琛�2.2.1銆�
+        if (busFlowCmd.getAuditor() != null && busFlowCmd.getOrderStatus() != null) {
+            switch (openEnum) {
+                case CREATE:
+                    break;
+                case SUBMIT:
+                    result = ExecuteTodo(busFlowCmd, SudiActionEnum.FinishTodo);
+                    break;
+                case BACK:
+                    result = ExecuteTodo(busFlowCmd, SudiActionEnum.FinishTodo);
+                    break;
+                case REVOKE:
+                    result = ExecuteTodo(busFlowCmd, SudiActionEnum.CancelTodo);
+                    break;
+                default:
+                    BaseResultModel<Boolean> ErrorResult = new BaseResultModel<>();
+                    ErrorResult.setErrorMessage("娌℃湁褰撳墠鎿嶄綔鏂规硶");
+                    ErrorResult.setErrorCode(ResponseCode.DATA_VERIFY_EXCEPTION.value());
+            }
+        }
+        if (result.getIsSuccess()) {
+            if (busFlowCmd.getNextAuditor() != null && busFlowCmd.getNextAuditor().split(",").length > 0) {
+                result = ExecuteTodo(busFlowCmd, SudiActionEnum.CreateTodo);
+            }
+        }
+        busFlowCmd.setExecutionStatus(result.getIsSuccess() ? ExecutionStatusEnum.Succeeded.getIndex() : ExecutionStatusEnum.Retry.getIndex());
+        BusFlowPo busFlowPo = BusFlowConvert.cmdToPo(busFlowCmd);
+        int i = busFlowMapper.updateById(busFlowPo);
+        if (i < 1) {
+            BaseResultModel<Boolean> ErrorResult1 = new BaseResultModel<>();
+            ErrorResult1.setErrorMessage("鏇存柊娴佺▼澶勭悊杩囩▼澶辫触");
+            ErrorResult1.setErrorCode(ResponseCode.DATA_VERIFY_EXCEPTION.value());
+            result = ErrorResult1;
+        }
+        return result.getIsSuccess();
+    }
+
+
+    private BaseResultModel<Boolean> ExecuteTodo(BusFlowCmd busFlowCmd, SudiActionEnum sudiActionEnum) {
+            BaseResultModel<Boolean> result = new SuccessResultModel<>();
+            result.setIsSuccess(true);
+            switch (sudiActionEnum){
+                case FinishTodo:
+                    result = FinishTodo(busFlowCmd);
+                    break;
+                case CancelTodo:
+                    result = CancelTodo(busFlowCmd);
+                    break;
+                case CreateTodo:
+                    result = CreateTodo(busFlowCmd);
+                    break;
+                default:
+                    break;
+            }
+            //todo 5
+            for (int i = 0; i < Integer.parseInt(SendTimes); i++) {
+                if (result.getIsSuccess()) {
+                    busFlowCmd.setLog(JSONObject.toJSONString(new ArrayList<String>()));
+                } else {
+                    String log = JSONObject.toJSONString(busFlowCmd.getLog());
+                    log.concat(result.getErrorMessage());
+                    busFlowCmd.setLog(JSONObject.toJSONString(log));
+                }
+            }
+            BusFlowPo busFlowPo = BusFlowConvert.cmdToPo(busFlowCmd);
+            Integer updated = busFlowMapper.updateById(busFlowPo);
+            if (updated < 1){
+                ExceptionUtil.getException(null,"鏇存柊娴佺▼澶勭悊澶辫触");
+            }
+            return result;
+    }
+
+
+
+    private BaseResultModel<Boolean> FinishTodo(BusFlowCmd busFlowCmd) {
+        BaseResultModel<Boolean> result = new SuccessResultModel<>();
+        if (busFlowCmd.getAuditor() != null) {
+            Integer executionStatus = busFlowCmd.getExecutionStatus();
+            if(executionStatus != ExecutionStatusEnum.Succeeded.getIndex()) {
+                if (busFlowCmd.getNextOrderStatus() != OrderStatusEnum.BACK.getName()) {
+                    List<BusFlowPo> busFlows = busFlowMapper.selectList(new QueryWrapper<BusFlowPo>().eq("apply_code",busFlowCmd.getApplyCode()).orderByDesc("create_date"));
+                    BusFlowPo busFlow = busFlows.get(1);
+                    busFlowCmd.setId(busFlow.getId());
+                    if (busFlow.getId() == null) {
+                        ExceptionUtil.getException(null,"鏈壘鍒伴渶瑕佸畬鎴愮殑寰呭姙id");
+                    }
+                    String nonce = "3L6nnjbX";
+                    String timestamp=System.currentTimeMillis()+"";
+                    // 鍒涘缓httpGet杩滅▼杩炴帴瀹炰緥
+                    String signature = null;
+                    String loginName=loginPortalService.getLoginUser().getUserName();
+                    String summary =  SudySignUtil.buildSummary(algorithm,loginName);
+                    try {
+                        signature = SudySignUtil.buildSign(algorithm,appCode,timestamp,nonce,null,secret);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    String taskBizId = busFlowCmd.getId().toString();
+                    TaskVO taskVO = new TaskVO();
+                    taskVO.setTaskBizId(taskBizId);
+                    doneTask(taskBizId,signature,nonce,timestamp,loginName);
+                }
+                busFlowCmd.setExecutionStatus(ExecutionStatusEnum.Succeeded.getIndex());
+                BusFlowPo busFlowPo = BusFlowConvert.cmdToPo(busFlowCmd);
+                int updated = busFlowMapper.updateById(busFlowPo);
+                if (updated < 1) {
+                    ExceptionUtil.getException(null,"鏇存柊娴佺▼澶勭悊杩囩▼澶辫触");
+                }
+            }
+        }
+        result.setIsSuccess(true);
+        return result;
+    }
+
+    private BaseResultModel<Boolean> CancelTodo(BusFlowCmd busFlowCmd)
+    {
+        BaseResultModel<Boolean> result = new SuccessResultModel<>();
+        {
+            if (busFlowCmd.getAuditor() != null)
+            {
+                int updated = 0;
+                String auditor = busFlowCmd.getAuditor();
+                List<BusFlowUserModel> busFlowUserModels = JSONArray.parseArray(auditor, BusFlowUserModel.class);
+                BusFlowUserModel auditorModel = busFlowUserModels.get(0);
+                if (auditorModel.getExecutionStatus() != ExecutionStatusEnum.Succeeded.getIndex()) {
+                    BusFlowPo busFlowPo = busFlowMapper.selectOne(new QueryWrapper<BusFlowPo>().eq("documentId",busFlowCmd.getDocumentId()).eq("next_order_status",busFlowCmd.getNextOrderStatus()));
+                    busFlowCmd.setTaskBizId(busFlowPo.getId().toString());
+                    if (auditorModel.getExecutionStatus() == ExecutionStatusEnum.Unexecuted.getIndex()) {
+                        if(busFlowCmd.getIsOrderStatusChanged() == false)
+                        {
+                            String nonce = "3L6nnjbX";
+                            String timestamp=System.currentTimeMillis()+"";
+                            // 鍒涘缓httpGet杩滅▼杩炴帴瀹炰緥
+                            String signature = null;
+                            String loginName=loginPortalService.getLoginUser().getUserName();
+                            try {
+                                signature = SudySignUtil.buildSign(algorithm,appCode,timestamp,nonce,null,secret);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                            String taskBizId = busFlowCmd.getId().toString();
+                            removePartipantsTask(signature,nonce,timestamp,taskBizId,loginName);
+                        }
+                        auditorModel.setExecutionStatus(ExecutionStatusEnum.DeletePerson.getIndex());
+                        busFlowCmd.setAuditor(JSONArray.toJSONString(auditorModel));
+                        BusFlowPo busFlowPo1 = BusFlowConvert.cmdToPo(busFlowCmd);
+                        updated = busFlowMapper.updateById(busFlowPo1);
+                        if (updated < 1){
+                            ExceptionUtil.getException(null,"鏇存柊娴佺▼澶勭悊杩囩▼澶辫触");
+                        }
+                    }
+                    // 杩藉姞璐d换浜�
+                    if (auditorModel.getExecutionStatus() == ExecutionStatusEnum.DeletePerson.getIndex()) {
+                        if (busFlowCmd.getIsOrderStatusChanged() == false)
+                        {
+                            String nonce = "3L6nnjbX";
+                            String timestamp=System.currentTimeMillis()+"";
+                            // 鍒涘缓httpGet杩滅▼杩炴帴瀹炰緥
+                            String signature = null;
+                            String loginName=loginPortalService.getLoginUser().getUserName();
+                            try {
+                                signature = SudySignUtil.buildSign(algorithm,appCode,timestamp,nonce,null,secret);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                            String taskBizId = busFlowCmd.getId().toString();
+                            addPartipantsTask(signature,nonce,timestamp,taskBizId,loginName);
+                        }
+                        auditorModel.setExecutionStatus(busFlowCmd.getIsOrderStatusChanged() == true ? ExecutionStatusEnum.AdditionalPerson.getIndex() : ExecutionStatusEnum.Succeeded.getIndex());
+                        busFlowCmd.setAuditor(JSONArray.toJSONString(auditorModel));
+                        BusFlowPo busFlowPo1 = BusFlowConvert.cmdToPo(busFlowCmd);
+                        updated = busFlowMapper.updateById(busFlowPo1);
+                        if (updated < 1){
+                            ExceptionUtil.getException(null,"鏇存柊娴佺▼澶勭悊杩囩▼澶辫触");
+                        }
+
+                    }
+                    //鑻ユ敼鍙樿妭鐐癸紝鍒欏垹闄ゅ鏍歌妭鐐圭殑寰呭姙浠诲姟
+                    if (auditorModel.getExecutionStatus() == ExecutionStatusEnum.AdditionalPerson.getIndex())
+                    {
+                        if (busFlowCmd.getIsOrderStatusChanged() == true)
+                        {
+                            BusFlowPo busFlow = busFlowMapper.selectOne(new QueryWrapper<BusFlowPo>().eq("documentId",busFlowCmd.getDocumentId()).eq("next_order_status",busFlowCmd.getNextOrderStatus()));
+                            busFlowCmd.setTaskBizId(busFlow.getId().toString());
+                            String nonce = "3L6nnjbX";
+                            String timestamp=System.currentTimeMillis()+"";
+                            // 鍒涘缓httpGet杩滅▼杩炴帴瀹炰緥
+                            String signature = null;
+                            try {
+                                signature = SudySignUtil.buildSign(algorithm,appCode,timestamp,nonce,null,secret);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                            String taskBizId = busFlowCmd.getId().toString();
+                            deleteTask(taskBizId,signature,nonce,timestamp);
+                        }
+                    }
+                    auditorModel.setExecutionStatus(ExecutionStatusEnum.Succeeded.getIndex());
+                    busFlowCmd.setAuditor(JSONArray.toJSONString(auditorModel));
+                    BusFlowPo busFlowPo1 = BusFlowConvert.cmdToPo(busFlowCmd);
+                    updated = busFlowMapper.updateById(busFlowPo1);
+                    if (updated < 1){
+                        ExceptionUtil.getException(null,"鏇存柊娴佺▼澶勭悊杩囩▼澶辫触");
+                    }
+                }
+            }
+            result.setIsSuccess(true);
+            return result;
+        }
+    }
+
+    private BaseResultModel<Boolean> CreateTodo(BusFlowCmd busFlowCmd) {
+        BaseResultModel<Boolean> result = new SuccessResultModel<>();
+        if (busFlowCmd.getNextAuditor() != null)
+            {
+                String nextAuditor = busFlowCmd.getNextAuditor();
+                List<BusFlowUserModel> nextAuditors = JSONArray.parseArray(nextAuditor, BusFlowUserModel.class);
+                //List<BusFlowUserModel> collect = nextAuditors.stream().filter(busFlowUserModel -> ExecutionStatusEnum.Succeeded.getIndex() == busFlowUserModel.getExecutionStatus()).collect(Collectors.toList());
+                List<BusFlowUserModel> collect = nextAuditors;
+                if(collect.size() != 0)
+                {
+                    if (busFlowCmd.getIsRejected() != true) {
+                        if(busFlowCmd.getIsOrderStatusChanged() == true) {
+                            ExpenseReimbursementPo order = expenseReimbursementMapper.selectOne(new QueryWrapper<ExpenseReimbursementPo>().eq("reimbursement_code", busFlowCmd.getApplyCode()));
+                            busFlowCmd.setApplyReason(order.getApplyReason());
+                            String nonce = "3L6nnjbX";
+                            String timestamp=System.currentTimeMillis()+"";
+                            // 鍒涘缓httpGet杩滅▼杩炴帴瀹炰緥
+                            String signature = null;
+                            String loginName = loginPortalService.getLoginUser().getUserName();
+                            String summary =  SudySignUtil.buildSummary(algorithm,loginName);
+                            try {
+                                signature = SudySignUtil.buildSign(algorithm,appCode,timestamp,nonce,null,secret);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                            String taskBizId = busFlowCmd.getId().toString();
+                            TaskVO taskVO = new TaskVO();
+                            taskVO.setTaskBizId(taskBizId);
+                            createTask(taskVO,signature,nonce,timestamp,loginName);
+                        }
+                        else
+                        {
+                            BusFlowPo busFlow = busFlowMapper.selectOne(new QueryWrapper<BusFlowPo>().eq("documentId",busFlowCmd.getDocumentId()).eq("next_order_status",busFlowCmd.getNextOrderStatus()));
+                            String nextAuditor1 = busFlow.getNextAuditor();
+                            List<BusFlowUserModel> nextAuditors1 = JSONArray.parseArray(nextAuditor1, BusFlowUserModel.class);
+                            List<BusFlowUserModel> collect1 = collect.stream().filter(obj -> find(obj.getUserId(), nextAuditors1)).collect(Collectors.toList());
+                            if(collect1.size() > 0)
+                            {
+                                String nonce = "3L6nnjbX";
+                                String timestamp=System.currentTimeMillis()+"";
+                                // 鍒涘缓httpGet杩滅▼杩炴帴瀹炰緥
+                                String signature = null;
+                                String loginName="admin";
+                                try {
+                                    signature = SudySignUtil.buildSign(algorithm,appCode,timestamp,nonce,null,secret);
+                                } catch (Exception e) {
+                                    e.printStackTrace();
+                                }
+                                String taskBizId = busFlowCmd.getId().toString();
+                                addPartipantsTask(signature,nonce,timestamp,taskBizId,loginName);
+                            }
+                        }
+                    }
+                    nextAuditors.forEach(e -> e.setExecutionStatus(ExecutionStatusEnum.Succeeded.getIndex()));
+                    busFlowCmd.setNextAuditor(JSONArray.toJSONString(nextAuditors));
+                    BusFlowPo busFlowPo = BusFlowConvert.cmdToPo(busFlowCmd);
+                    int updated = busFlowMapper.updateById(busFlowPo);
+                    if (updated < 1) {
+                        ExceptionUtil.getException(null,"鏇存柊娴佺▼澶勭悊杩囩▼澶辫触");
+                    }
+                }
+            }
+        result.setIsSuccess(true);
+        return result;
+    }
+
+    public Boolean find(String empNumber, List<BusFlowUserModel> list) {
+        for (int i = 0; i < list.size(); i++) {
+            if (list.get(i).getUserId() .equals(empNumber)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+        /**
+         * 2.2.1
+         * 鍒涘缓浠诲姟
+         * @throws Exception
+         */
+        private void createTask(TaskVO task, String signature, String nonce, String timestamp, String loginName) {
+            String url = Host + "/_web/_apps/taskcenter/api/v3/taskcenter/app/" + appCode + "/task/category/" + taskCategoryCode + ".rst";
+
+//        url = url + "_method=PUT";
+            Date date = new Date();
+            task.setCreatorId(loginName);
+            task.setDeadLine(date);
+            task.setImportance(TaskVO.IMPORTANCE_MIDDLE);
+            task.setState(TaskVO.STATE_UNDO);
+            task.setSubTitle("璇峰噯鏃跺弬鍔�");
+            task.setTitle(task.getTaskBizId() + "-璇峰亣鐢宠");
+            task.setUrl("http://www.baidu.com");
+            task.setDoneUrl("http://www.google.cn/");
+//        //浠诲姟鍙備笌鑰�
+            ParticipantVO[] participantVOS = new ParticipantVO[1];
+            ParticipantVO participantVO = new ParticipantVO();
+            participantVO.setType(ParticipantVO.TYPE_USER);
+            participantVO.setUserCode(loginName);
+//        participantVO.setMonitor(true);
+            participantVOS[0] = participantVO;
+//
+//        ParticipantVO participantVO1 = new ParticipantVO();
+//        participantVO1.setType(ParticipantVO.TYPE_USER);
+//        participantVO1.setUserCode("admin");
+//        participantVO1.setMonitor(false);
+//        participantVOS[1] = participantVO1;
+
+//        ParticipantVO participantVO1 = new ParticipantVO();
+//        participantVO1.setType(ParticipantVO.TYPE_GROUP);
+//        participantVO1.setGroupName("eos_wlxxzxwlb");
+//        participantVOS[0] = participantVO1;
+//        ParticipantVO participantVO2 = new ParticipantVO();
+//        participantVO2.setType(ParticipantVO.TYPE_USER);
+//        participantVO2.setUserCode("999002");
+//        participantVOS[1] = participantVO2;
+//        ParticipantVO participantVO1 = new ParticipantVO();
+//        participantVO1.setType(ParticipantVO.TYPE_USER);
+//        participantVO1.setUserCode("010026");
+//        participantVOS[1] = participantVO1;
+            task.setParticipants(participantVOS);
+
+//        TaskVO  parentTaskVO = new TaskVO ();
+//        parentTaskVO.setProcessTrace(true);
+//        parentTaskVO.setCreatorId("admin");
+//        parentTaskVO.setTaskBizId("010010=04");
+//        parentTaskVO.setUrl("http://");
+//        parentTaskVO.setTitle("ffchen璇峰亣鐢宠");
+//        parentTaskVO.setCreateTime(new Date());
+//        participantVO = new ParticipantVO();
+//        participantVO.setUserCode("admin");
+//        participantVO.setType(0);
+//        participantVOS = new ParticipantVO[1];
+//        participantVOS[0] = participantVO;
+//        parentTaskVO.setParticipants(participantVOS);
+//        task.setParentTask(parentTaskVO);
+            doPost(url, JSON.toJSONString(task), signature, nonce, timestamp, null);
+        }
+
+
+    private void doneTask(String taskBizId,String signature,String nonce,String timestamp,String loginName){
+        String url = Host+"/_web/_apps/taskcenter/api/v3/taskcenter/app/"+appCode+"/task/"+ taskBizId+"/user/"+loginName+"/userDone.rst";
+        UserDoneAO userDoneAO = new UserDoneAO();
+        userDoneAO.setFinishTask(false);
+        userDoneAO.setDoneDate(new Date());
+        doPost(url,JSON.toJSONString(userDoneAO),signature,nonce,timestamp,null);
+    }
+
+    private void addPartipantsTask(String signature,String nonce,String timestamp,String taskBizId,String loginName){
+        String url = Host+"/_web/_apps/taskcenter/api/v3/taskcenter/app/"+ appCode +"/task/"+taskBizId+"/participant.rst";
+        ParticipantVO[] participants = new ParticipantVO[1];
+        ParticipantVO participant = new ParticipantVO();
+        participant.setType(ParticipantVO.TYPE_USER);
+        participant.setUserCode(loginName);
+        participants[0] = participant;
+        doPost(url,JSON.toJSONString(participants),signature,nonce,timestamp,null);
+    }
+
+    private void removePartipantsTask(String signature,String nonce,String timestamp,String taskBizId,String loginName){
+        String url = Host+"/_web/_apps/taskcenter/api/v3/taskcenter/app/"+appCode+"/task/" + taskBizId +"/participant.rst";
+        ParticipantVO[] participants = new ParticipantVO[1];
+        ParticipantVO participant = new ParticipantVO();
+        participant.setType(ParticipantVO.TYPE_USER);
+        participant.setUserCode(loginName);
+        participants[0] = participant;
+        doDelete(url,JSON.toJSONString(participants),signature,nonce,timestamp);
+    }
+
+    /**
+     * 2.2.2
+     * 鍒涘缓浠诲姟骞跺畬鎴�
+     * @throws Exception
+     */
+    private void createTaskAndUserDone (String signature, String nonce, String timestamp, String loginName, String taskBizId, String parentTaskBizId) throws Exception {
+        TaskVO task = new TaskVO();
+        Date date = new Date();
+        task.setCreatorId(loginName);
+        task.setDeadLine(date);
+        task.setUrl("http://");
+        task.setImportance(TaskVO.IMPORTANCE_MIDDLE);
+        task.setState(TaskVO.STATE_UNDO);
+        task.setSubTitle("test");
+        task.setTitle("second test3. bizId=tz2, cate=2, app=2, participant=0810035");
+        task.setTaskBizId(taskBizId);
+        //浠诲姟鍙備笌鑰�
+        ParticipantVO[] participantVOS = new ParticipantVO[1];
+        ParticipantVO participantVO = new ParticipantVO();
+        participantVO.setType(ParticipantVO.TYPE_USER);
+        participantVO.setUserCode(loginName);
+        participantVOS[0] = participantVO;
+        task.setParticipants(participantVOS);
+        String randomId = UUID.randomUUID().toString();
+        UserDoneAO userDoneAO = new UserDoneAO();
+        userDoneAO.setDoneDate(new Date());
+        userDoneAO.setFinishTask(true);
+        userDoneAO.setDelegate(false);
+        TaskAndDoneAO taskAndDoneAO = new TaskAndDoneAO();
+        taskAndDoneAO.setTaskVO(task);
+        taskAndDoneAO.setUserDoneAO(userDoneAO);
+
+        String url = Host + "/_web/_apps/taskcenter/api/v3/taskcenter/app/" + appCode + "/task/category/" + taskCategoryCode + "/done.rst?userId=" + loginName;
+        doPost(url, JSON.toJSONString(taskAndDoneAO), signature, nonce, timestamp, null);
+    }
+
+
+    /**
+     * 2.2.8
+     * 鍒犻櫎浠诲姟
+     * @param taskBizId 浠诲姟bizid
+     * @param signature
+     * @param nonce
+     * @param timestamp
+     */
+    private void deleteTask (String taskBizId, String signature, String nonce, String timestamp){
+        String url = Host + "/_web/_apps/taskcenter/api/v3/taskcenter/app/" + appCode + "/task/" + taskBizId + "/delete.rst?" +
+                "cascade=true";
+
+        doPost(url, null, signature, nonce, timestamp, null);
+    }
+
+    /**
+     * 2.2.10
+     * 瀹屾垚浠诲姟
+     * @param taskBizId 浠诲姟bizid
+     * @param signature
+     * @param nonce
+     * @param timestamp
+     */
+    private void finishTask (String taskBizId, String signature, String nonce, String timestamp, String loginName){
+        String url = Host + "/_web/_apps/taskcenter/api/v3/taskcenter/app/" + appCode + "/task/" + taskBizId + "/finish.rst";
+        FinishTaskVO finishTaskVO = new FinishTaskVO();
+        finishTaskVO.setDoneDate(new Date());
+        doPost(url, JSON.toJSONString(finishTaskVO), signature, nonce, timestamp, null);
+    }
+
+
+    public String doPost (String url, String json, String signature, String nonce, String timestamp, String summary){
+        System.out.println(url);
+        CloseableHttpClient httpClient = null;
+        CloseableHttpResponse response = null;
+        String result = "";
+        try {
+            // 閫氳繃鍧€榛樿閰嶇疆鍒涘缓涓€涓猦ttpClient瀹炰緥
+            httpClient = HttpClients.createDefault();
+            HttpPost httpPost = new HttpPost(url);
+            System.out.println(json);
+            if (json != null) {
+                StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
+                httpPost.setEntity(stringEntity);
+            }
+            // 璁剧疆璇锋眰澶翠俊鎭紝閴存潈
+            httpPost.setHeader("sd-appid", appCode);
+            httpPost.setHeader("sd-algorithm", algorithm);
+            httpPost.setHeader("sd-timestamp", timestamp);
+            httpPost.setHeader("sd-nonce", nonce);
+            httpPost.setHeader("sd-signature", signature);
+            if (summary != null) {
+                httpPost.setHeader("sd-summary", summary);
+            }
+            // 璁剧疆閰嶇疆璇锋眰鍙傛暟
+            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 杩炴帴涓绘満鏈嶅姟瓒呮椂鏃堕棿
+                    .setConnectionRequestTimeout(35000)// 璇锋眰瓒呮椂鏃堕棿
+                    .setSocketTimeout(60000)// 鏁版嵁璇诲彇瓒呮椂鏃堕棿
+                    .build();
+            // 涓篽ttpGet瀹炰緥璁剧疆閰嶇疆
+            httpPost.setConfig(requestConfig);
+            // 鎵цget璇锋眰寰楀埌杩斿洖瀵硅薄
+            response = httpClient.execute(httpPost);
+            // 閫氳繃杩斿洖瀵硅薄鑾峰彇杩斿洖鏁版嵁
+            HttpEntity entity = response.getEntity();
+            // 閫氳繃EntityUtils涓殑toString鏂规硶灏嗙粨鏋滆浆鎹负瀛楃涓�
+            result = EntityUtils.toString(entity);
+            System.out.println(result);
+        } catch (ClientProtocolException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            // 鍏抽棴璧勬簮
+            if (null != response) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (null != httpClient) {
+                try {
+                    httpClient.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return result;
+    }
+
+    public String doDelete(String url,String json,String signature,String nonce,String timestamp) {
+        System.out.println(url);
+        CloseableHttpClient httpClient = null;
+        CloseableHttpResponse response = null;
+        String result = "";
+        try {
+            // 閫氳繃鍧€榛樿閰嶇疆鍒涘缓涓€涓猦ttpClient瀹炰緥
+            httpClient = HttpClients.createDefault();
+            MyHttpDelete httpDelete = new MyHttpDelete(url);
+            // 璁剧疆閰嶇疆璇锋眰鍙傛暟
+            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 杩炴帴涓绘満鏈嶅姟瓒呮椂鏃堕棿
+                    .setConnectionRequestTimeout(35000)// 璇锋眰瓒呮椂鏃堕棿
+                    .setSocketTimeout(60000)// 鏁版嵁璇诲彇瓒呮椂鏃堕棿
+                    .build();
+            // 涓篽ttpGet瀹炰緥璁剧疆閰嶇疆
+            httpDelete.setConfig(requestConfig);
+            if(json != null) {
+                StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
+                httpDelete.setEntity(stringEntity);
+            }
+            // 璁剧疆璇锋眰澶翠俊鎭紝閴存潈
+            httpDelete.setHeader("sd-appid", appCode);
+            httpDelete.setHeader("sd-algorithm", algorithm);
+            httpDelete.setHeader("sd-timestamp", timestamp);
+            httpDelete.setHeader("sd-nonce", nonce);
+            httpDelete.setHeader("sd-signature", signature);
+            // 鎵цget璇锋眰寰楀埌杩斿洖瀵硅薄
+            response = httpClient.execute(httpDelete);
+            // 閫氳繃杩斿洖瀵硅薄鑾峰彇杩斿洖鏁版嵁
+            HttpEntity entity = response.getEntity();
+            // 閫氳繃EntityUtils涓殑toString鏂规硶灏嗙粨鏋滆浆鎹负瀛楃涓�
+            result = EntityUtils.toString(entity);
+            System.out.println(result);
+        } catch (ClientProtocolException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            // 鍏抽棴璧勬簮
+            if (null != response) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (null != httpClient) {
+                try {
+                    httpClient.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return result;
+    }
+}
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/ExpenseReimbursementServiceImpl.java b/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/ExpenseReimbursementServiceImpl.java
index 075e2da225445cb9afe67e280e13c4ea2ba74af7..5a1d25830fa3b283459c32285840087b03edc262 100644
--- a/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/ExpenseReimbursementServiceImpl.java
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/ExpenseReimbursementServiceImpl.java
@@ -69,6 +69,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.activiti.bpmn.model.ExtensionAttribute;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.poi.ss.formula.functions.T;
+import org.springframework.amqp.core.AmqpTemplate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
@@ -153,6 +154,12 @@ public class ExpenseReimbursementServiceImpl implements ExpenseReimbursementServ
     @Lazy
     private PreExpenseApplyService preExpenseApplyService;
 
+    @Autowired
+    private BusFlowService busFlowService;
+
+    @Autowired
+    private AmqpTemplate amqpTemplate;
+
     @Override
     public Pagination<PreExpenseApplyOut> listPreExpenseApply(PreExpenseApplyQuery expenseApplyQuery) {
         try {
@@ -224,7 +231,6 @@ public class ExpenseReimbursementServiceImpl implements ExpenseReimbursementServ
             //钖祫娌′紶
             expenseReimbursementCmd.setApprovalDetailId(ObjectUtils.isEmpty(expenseReimbursementCmd.getApprovalDetailId()) ? null : expenseReimbursementCmd.getApprovalDetailId());
         }
-
         //鏀跺叆璁ら鍜岄寮€鍙戠エ娌℃湁鎶ラ攢椤圭洰
         if (ObjectUtils.isNotEmpty(expenseReimbursementCmd.getFundsProject())) {
             //鍒涘缓鎶ラ攢鍗� 1.2-鍏ュ弬鏍¢獙-鏍¢獙缁忚垂缂栧彿涓庤祫閲戞€ц川
@@ -1017,7 +1023,7 @@ public class ExpenseReimbursementServiceImpl implements ExpenseReimbursementServ
     public T createFlow(ExpenseReimbursementCmd expenseReimbursementCmd) {
         assert expenseReimbursementCmd != null;
         //娴佺▼閰嶇疆
-        FlowCmd flowCmd = FlowCmd.builder().businessKey(String.valueOf(expenseReimbursementCmd.getId())).build();
+        FlowCmd flowCmd = FlowCmd.builder().businessKey(String.valueOf(expenseReimbursementCmd.getReimbursementCode())).build();
         flowCmd.setApplyUserId(expenseReimbursementCmd.getApplicantNo());
         flowCmd.setApprover(expenseReimbursementCmd.getApplicantNo());
         flowCmd.setBusinessData(BeanUtil.beanToMap(expenseReimbursementCmd));
@@ -1070,6 +1076,7 @@ public class ExpenseReimbursementServiceImpl implements ExpenseReimbursementServ
                 }
                 flowCmd.getBusinessData().put("nodeId", flowCmd.getActivityId());
                 FlowNode activityNode = activityNodeOptional.get();
+
                 //璁剧疆瀹℃壒鍚庡崟鎹姸鎬�
                 expenseReimbursementCmd.setOrderStatus(activityNode.getName());
                 //鏄惁閫夋嫨鍔犵浜哄睘鎬�
@@ -1095,7 +1102,9 @@ public class ExpenseReimbursementServiceImpl implements ExpenseReimbursementServ
                 }
             }
             flowCmd.setOpinion(ObjectUtils.isEmpty(flowCmd.getOpinion()) ? "瀹℃壒閫氳繃" : flowCmd.getOpinion());
-            flowService.submitFlow(flowCmd);
+            //flowCmd.setBusinessData(BeanUtil.beanToMap(expenseReimbursementCmd));
+            flowCmd.setBusinessKey(expenseReimbursementCmd.getReimbursementCode());
+            flowService.saveFlow(OpenEnum.SUBMIT,flowCmd);
         } catch (Exception e) {
             idempotentService.saveIdempotent(IdempotentCmd.builder().id(expenseReimbursementCmd.getId()).orderStatus(IdempotentEnum.SubmitFlow.getIndex()).build());
             throw ExceptionUtil.getException(null, "瀹℃壒楠岃瘉澶辫触锛�" + e.getMessage());
@@ -1116,6 +1125,7 @@ public class ExpenseReimbursementServiceImpl implements ExpenseReimbursementServ
         // 椹冲洖鍒板鎵归┏鍥炶妭鐐�
         Optional<FlowNode> rejectNode = processDefinitionInfo.getFlowNodeList().stream().filter(s -> OrderStatusEnum.BACK.getName().equals(s.getName())).findFirst();
         rejectNode.ifPresent(flowNode -> flowCmd.setActivityId(flowNode.getId()));
+        flowCmd.setBusinessKey(expenseReimbursementCmd.getReimbursementCode());
         if (ObjectUtils.isNotEmpty(flowCmd)) {
             log.info("璋冪敤activit瀹℃壒閫€鍥�:" + flowCmd);
             flowService.saveFlow(OpenEnum.BACK, flowCmd);
@@ -1137,7 +1147,6 @@ public class ExpenseReimbursementServiceImpl implements ExpenseReimbursementServ
         signatureService.getAndSaveSignature(signatureCmd);
         return null;
     }
-
     /**
      * 娑堟伅鍐呭鏁村悎
      *
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/FlowServiceImpl.java b/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/FlowServiceImpl.java
index c37d9cb33e784793bd275ed23a8f5821b29cb19d..1f009535ff53de94385d1d7b36e26b8e7d325b19 100644
--- a/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/FlowServiceImpl.java
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/FlowServiceImpl.java
@@ -1,6 +1,7 @@
 package com.seasky.flowportal.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.seasky.core.common.Result;
 import com.seasky.core.ddd.utils.MapperUtils;
@@ -22,6 +23,8 @@ import com.seasky.flow.dto.task.NodeOut;
 import com.seasky.flow.dto.task.TaskCmd;
 import com.seasky.flow.dto.task.TaskQueryQry;
 import com.seasky.flowportal.config.BaseConfigProperties;
+import com.seasky.flowportal.domain.po.BusFlowPo;
+import com.seasky.flowportal.domain.po.BusFlowUserModel;
 import com.seasky.flowportal.domain.po.ExpenseReimbursementPo;
 import com.seasky.flowportal.dto.flow.FlowCmd;
 import com.seasky.flowportal.dto.flow.FlowOut;
@@ -29,15 +32,18 @@ import com.seasky.flowportal.dto.flow.FlowQuery;
 import com.seasky.flowportal.dto.flowTool.FlowToolOut;
 import com.seasky.flowportal.dto.node.NodeInfoOut;
 import com.seasky.flowportal.dto.user.UserInfoOut;
+import com.seasky.flowportal.dto.user.UserInfoQuery;
 import com.seasky.flowportal.enums.FlowOpenEnum;
 import com.seasky.flowportal.enums.OpenEnum;
 import com.seasky.flowportal.enums.OrderStatusEnum;
 import com.seasky.flowportal.mapper.ExpenseReimbursementMapper;
 import com.seasky.flowportal.service.BaseConfigService;
+import com.seasky.flowportal.service.BusFlowService;
 import com.seasky.flowportal.service.ExternalDataService;
 import com.seasky.flowportal.service.FlowService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.amqp.core.AmqpTemplate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
@@ -81,6 +87,12 @@ public class FlowServiceImpl extends FlowService {
     @Lazy
     private BaseConfigService baseConfigService;
 
+    @Autowired
+    private BusFlowService busFlowService;
+
+    @Autowired
+    private AmqpTemplate amqpTemplate;
+
 
     @Override
     public Map<String, String> getFlowInfo(String flowName) {
@@ -186,9 +198,28 @@ public class FlowServiceImpl extends FlowService {
     public String saveFlow(OpenEnum open, FlowCmd flowCmd) {
         log.info("鎿嶄綔{},鍙傛暟{}", open.getName(), JSON.toJSONString(flowCmd));
         String result = "";
+        String orderstatus = "";
+        Boolean flag = baseConfigService.getBaseConfigProperties().getNeedSaveBusFlow();
+        BusFlowPo busFlowPo = new BusFlowPo();
+        if (flag && open != OpenEnum.CREATE){
+            TaskQueryQry taskQueryQry = new TaskQueryQry();
+            taskQueryQry.setProcessInstanceId(flowCmd.getProcessInstanceId());
+            Result<TaskOut> taskListByProcessInstanceId = iTaskController.getTaskListByProcessInstanceId(taskQueryQry);
+            TaskOut taskOut = taskListByProcessInstanceId.getData().get(0);
+            orderstatus = taskOut.getName();
+        }
         switch (open) {
             case CREATE:
                 result = createFlow(flowCmd);
+                if (ObjectUtils.isNotEmpty(result)){
+                    TaskQueryQry taskQueryQry = new TaskQueryQry();
+                    taskQueryQry.setProcessInstanceId(result);
+                    Result<NodeOut> nextNodeByProcessInstanceId = iTaskController.getNextNodeByProcessInstanceId(taskQueryQry);
+                    NodeOut nodeOut = nextNodeByProcessInstanceId.getData().get(0);
+                    String nextOrderStatus = nodeOut.getNodeName();
+                    flowCmd.setProcessInstanceId(result);
+                }
+                /*busFlowPo.setNextAuditor(nodeOut.getAssignee());*/
                 break;
             case SUBMIT:
                 result = submitFlow(flowCmd);
@@ -205,9 +236,140 @@ public class FlowServiceImpl extends FlowService {
             default:
                 throw ExceptionUtil.getException(null, "娌℃湁褰撳墠鎿嶄綔鏂规硶");
         }
+        //iTaskController.getNextNodeByProcessInstanceId()  鑾峰彇涓嬩竴鑺傜偣鍚嶇О
+        //todo 濡傛灉 涓� true  鍒欒蛋鑻忚开鎺ュ彛
+        if(flag){
+            saveBusFlow(open,flowCmd,orderstatus);
+        }
         return result;
     }
 
+    public void saveBusFlow(OpenEnum open,FlowCmd flowCmd,String orderStatus){
+        /*
+        *
+        * //鑾峰彇鍗曞彿
+				var order = ExpenseReimbursementRepository.SelectOrder(new ExpenseReimbursementInputModel { PKID = model.DocumentID });
+				if (order.OrderTypes == EnumOrderTypes.鍓嶇疆鐢宠)
+				{
+					var getPrefix = PreApplyHelper.GetWebUrlPreFix(order.ApplyType);
+					if (!getPrefix.IsSuccess)
+                    {
+						LogWriter.WriteLog(EnumLogLevel.Fatal, "SaveBusFlow", "MyAppsService", "", getPrefix.ErrorMessage);
+						return;
+					}
+					order.WebUrl = getPrefix.Data + order.ApplyCode;
+				}
+				//鑾峰彇瀹℃牳浜�
+				BusFlowUserModel auditor = null;
+				bool noAuditor = open == EnumOpen.淇濆瓨 || orderStatus == EnumBaseFlowStatus.瀹屾垚;
+				if (!noAuditor)
+				{
+					var userInfo = UserRepository.SelectWithKeys(new UserModel { UserID = BaseData.BLL.ApplicationContext.Current.UserId });
+					auditor = new BusFlowUserModel { UserId = userInfo.UserID, UserNo = userInfo.UserNo, UserName = userInfo.UserName };
+				}
+				//鑾峰彇寰呭姙鑺傜偣
+				var resultGetCurNode = GetCurNodeInfoByDocumentID(model);
+				var nextOrderStatus = resultGetCurNode.IsSuccess ? resultGetCurNode.Data?.Values?.FirstOrDefault() : string.Empty;
+				//鑾峰彇寰呭姙浜�
+				var nextAuditor = new List<BusFlowUserModel>();
+				bool noNextAuditor = nextOrderStatus == EnumBaseFlowStatus.瀹屾垚 || nextOrderStatus == EnumBaseFlowStatus.瀹℃壒椹冲洖;
+				if (!noNextAuditor)
+				{
+					var resultUsers = GetAuditorByDocumentID(model);
+					if (resultUsers.IsSuccess)
+					{
+						foreach (var item in resultUsers.Data)
+						{
+							var userInfo = UserRepository.SelectWithKeys(new UserModel { UserID = Guid.Parse(item) });
+							if (userInfo == null) continue;
+							nextAuditor.Add(new BusFlowUserModel { UserId = userInfo.UserID, UserNo = userInfo.UserNo, UserName = userInfo.UserName });
+						}
+					}
+				}
+				var resultCreateAndPushBusFlow = BusFlowService.CreateAndPushBusFlow(new BusFlowInputModel
+				{
+					Open = open,
+					DocumentID = model.DocumentID,
+					ApplyCode = order.ApplyCode,
+					OrderStatus = orderStatus,
+					AuditorModel = auditor,
+					NextOrderStatus = nextOrderStatus,
+					NextAuditorModel = nextAuditor,
+					WebUrl = order.WebUrl
+				});
+				var busFlow = resultCreateAndPushBusFlow.Data;
+				LogWriter.WriteLog(EnumLogLevel.Debug, "SaveBusFlow", "MyAppsService", "", $"閫€鍑烘柟娉曪細busFlow: {JsonConvert.SerializeObject(busFlow)}", null);
+			}
+			catch (Exception e)
+			{
+				LogWriter.WriteLog(EnumLogLevel.Fatal, "SaveBusFlow", "MyAppsService", "", $"淇濆瓨娴佺▼澶勭悊杩囩▼澶辫触", e);
+			}
+			return;
+        * */
+        UserInfoOut loginUser = null;
+        if(ObjectUtils.isNotEmpty(flowCmd.getApplyUserId())){
+            loginUser = externalDataService.getUserInfoByUserNo(flowCmd.getApplyUserId());
+        }else{
+            loginUser = loginPortalService.getLoginUser();
+        }
+
+        String auditor = "{}";
+        //鑾峰彇鍓嶇疆鐢宠鍗曞彿
+        Map<String, Object> businessData = flowCmd.getBusinessData();
+        String applyCode = "";
+        String businessKey = flowCmd.getBusinessKey();
+        applyCode = businessKey;
+        if ("null".equals(applyCode)){
+            applyCode = String.valueOf(businessData.get("reimbursementCode"));
+        }
+
+        //鑾峰彇瀹℃牳浜�
+        Boolean flag = OpenEnum.CREATE.equals(open) || OrderStatusEnum.FINISH.getName().equals(orderStatus);
+        if (!flag){
+            //鐢ㄦ埛id  鐢ㄦ埛宸ュ彿  鐢ㄦ埛鍚�   userId  userCode   userName
+            BusFlowUserModel auditor1 = new BusFlowUserModel();
+            auditor1.setUserId(loginUser.getUserId());
+            auditor1.setUserCode(loginUser.getUserNo());
+            auditor1.setUserName(loginUser.getUserName());
+            auditor = JSONArray.toJSONString(auditor1);
+        }
+        //鑾峰彇寰呭姙鑺傜偣
+        TaskQueryQry taskQueryQry = new TaskQueryQry();
+        taskQueryQry.setProcessInstanceId(flowCmd.getProcessInstanceId());
+        Result<NodeOut> nextNodeByProcessInstanceId = iTaskController.getNextNodeByProcessInstanceId(taskQueryQry);
+        NodeOut nodeOut = nextNodeByProcessInstanceId.getData().get(0);
+        String nextOrderStatus = nodeOut.getNodeName();
+        //鑾峰彇寰呭姙浜�
+        String nextAuditor = "[]";
+        Boolean flag1 = OrderStatusEnum.FINISH.getName().equals(nextOrderStatus) || OrderStatusEnum.BACK.getName().equals(nextOrderStatus);
+        if (! flag1){
+            TaskQueryQry taskQueryQry1 = new TaskQueryQry();
+            taskQueryQry1.setProcessInstanceId(flowCmd.getProcessInstanceId());
+            Result<TaskOut> taskListByProcessInstanceId = iTaskController.getTaskListByProcessInstanceId(taskQueryQry1);
+            List<BusFlowUserModel> nextAuditorList = new ArrayList<>();
+            for (TaskOut datum : taskListByProcessInstanceId.getData()) {
+                String assignee = datum.getAssignee();
+                UserInfoQuery userInfoQuery = new UserInfoQuery();
+                userInfoQuery.setUserNo(assignee);
+                UserInfoOut userInfo = externalDataService.getUserInfoByUserNo(assignee);
+                nextAuditorList.add(new BusFlowUserModel(userInfo.getUserId(),userInfo.getUserNo(),userInfo.getUserName(),null));
+            }
+            nextAuditor = JSONArray.toJSONString(nextAuditorList);
+        }
+        //璋冪敤 busflowService  createAndPushBusFlow
+        BusFlowPo busFlowPo = new BusFlowPo();
+        busFlowPo.setOpen(open.getIndex());
+        busFlowPo.setApplyCode(applyCode);
+        busFlowPo.setOrderStatus(orderStatus);
+        busFlowPo.setAuditor(auditor);
+        busFlowPo.setNextOrderStatus(nextOrderStatus);
+        busFlowPo.setNextAuditor(nextAuditor);
+        busFlowPo.setExecutionStatus(0);
+        busFlowPo.setDocumentId("");
+        busFlowPo.setLog("[]");
+        busFlowService.createAndPushBusFlow(busFlowPo);
+    }
+
     @Override
     public String createFlow(FlowCmd flowCmd) {
         ProcessCmd processCmd = MapperUtils.INSTANCE.map(ProcessCmd.class, flowCmd);
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/LoginPortalServiceImpl.java b/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/LoginPortalServiceImpl.java
index a0f79a7185fec366d929459cfd9aa84030b43b55..4a2bb4555ebe21c96788a1d111f8b72dfd9ecfba 100644
--- a/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/LoginPortalServiceImpl.java
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/service/impl/LoginPortalServiceImpl.java
@@ -119,7 +119,6 @@ public class LoginPortalServiceImpl implements LoginPortalService {
         Object currentUserObj = ShiroUtil.getCurrentUserObj();
         if (ObjectUtils.isEmpty(currentUserObj)) {
             Object userNo = ShiroUtil.getSession(ShiroUtil.getSessionId() + ":LoginUserNo");
-            userNo = "278";  //todo 鍘绘帀
             if (ObjectUtils.isEmpty(userNo)) {
                 throw new DataAccessException(
                         new Error(ResponseCode.LOGIN_OAUTH2_ERROR, null,
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/utils/MyHttpDelete.java b/ServiceSite/src/main/java/com/seasky/flowportal/utils/MyHttpDelete.java
new file mode 100644
index 0000000000000000000000000000000000000000..2595f88ea163a0958eb739844f38db6073139865
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/utils/MyHttpDelete.java
@@ -0,0 +1,24 @@
+package com.seasky.flowportal.utils;
+
+import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
+
+import java.net.URI;
+
+public class MyHttpDelete extends HttpEntityEnclosingRequestBase {
+    public static final String METHOD_NAME = "DELETE";
+    @Override
+    public String getMethod() {
+        return METHOD_NAME;
+    }
+    public MyHttpDelete(final String uri) {
+        super();
+        setURI(URI.create(uri));
+    }
+    public MyHttpDelete(final URI uri) {
+        super();
+        setURI(uri);
+    }
+    public MyHttpDelete() {
+        super();
+    }
+}
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/utils/StringUtil.java b/ServiceSite/src/main/java/com/seasky/flowportal/utils/StringUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f7c26b1fa131bcda5ec2f0bf4378e2812dee576
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/utils/StringUtil.java
@@ -0,0 +1,10 @@
+package com.seasky.flowportal.utils;
+
+/**
+ * 瀛楃涓插伐鍏风被
+ */
+public class StringUtil {
+    public static boolean isEmpty(String string) {
+        return string == null || string.length() == 0 || string.trim().equals("");
+    }
+}
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/utils/SudySignUtil.java b/ServiceSite/src/main/java/com/seasky/flowportal/utils/SudySignUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..9050bfbd173c607155a26a1be47941b1079a7c52
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/utils/SudySignUtil.java
@@ -0,0 +1,198 @@
+package com.seasky.flowportal.utils;
+
+import org.apache.commons.codec.binary.Hex;
+
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 瀵瑰寮€鏀剧鍚嶇畻娉曞伐鍏风被
+ * @author xhmeng
+ */
+public class SudySignUtil {
+    /**
+     * 绛惧悕绠楁硶绫诲瀷sha1
+     */
+    public static final String ALGORITHM_SHA1 = "SHA1";
+    /**
+     * 绛惧悕绠楁硶绫诲瀷sha-256
+     */
+    public static final String ALGORITHM_SHA256 = "SHA-256";
+    /**
+     * 绛惧悕绠楁硶绫诲瀷MD5
+     */
+    public static final String ALGORITHM_MD5 = "MD5";
+    /**
+     * 绛惧悕绠楁硶绫诲瀷HMAC-SHA256
+     */
+    public static final String ALGORITHM_HMACSHA256= "HMAC-SHA256";
+
+    /**
+     * 鏀寔鐨勭鍚嶇畻娉�
+     */
+    private static final List<String> allowedAlgorithms = new ArrayList<>();
+
+    static {
+        allowedAlgorithms.add(ALGORITHM_SHA1);
+        allowedAlgorithms.add(ALGORITHM_SHA256);
+        allowedAlgorithms.add(ALGORITHM_MD5);
+        allowedAlgorithms.add(ALGORITHM_HMACSHA256);
+    }
+
+
+
+    /**
+     * 鐢熸垚绛惧悕
+     * @param algorithm 绛惧悕绠楁硶銆係HA1,MD5锛孲HA-256,HMAC-SHA256
+     * @param appId 搴旂敤鏍囪瘑锛屾鏍囪瘑鏄彁鍓嶅垎閰嶇粰璋冪敤绯荤粺鐨�
+     * @param timestamp 鏃堕棿鎴炽€傞暱鏁存暟锛屾槸UNIX鏃堕棿鐨勬绉掓暟锛屽嵆浜х敓绛惧悕鏃剁殑鏃堕棿璺�1970骞�1鏈�1鏃ラ浂鏃剁殑姣鏁扮殑鍗佽繘鍒跺瓧绗︿覆銆�
+     *                  姝ゆ椂闂存埑浠h〃浜嗙鍚嶇殑鏃舵晥鎬э紝濡傛灉姝ゆ椂闂翠笌褰撳墠鏃堕棿宸ぇ浜庢煇涓€硷紙寤鸿涓嶈秴杩�20鍒嗛挓锛夋椂锛岀郴缁熻涓烘绛惧悕宸茬粡澶辨晥
+     * @param nonce 闅忔満鏁般€傜敤浜庡弬涓庣鍚嶈繍绠�
+     * @param summary  鎽樿锛屼笟鍔℃帴鍙e鍔犲瓧娈电殑hash鍊笺€傚弬涓庣鍚嶏紝杩涗竴姝ョ鍚嶇殑鍙傛暟鍊煎extraText=鈥渓oginName=0810035&userId=2鈥濓紝
+     *                 闇€瑕乭ash鍚庝紶杈擄紝涓氬姟绯荤粺鍦ㄦ牎楠宻ign鐨勫熀纭€涓婅繘涓€姝ユ牎楠屾鍊笺€俬ex锛坔ash锛坋xtraText锛夛級鍚庣殑鍐呭,
+     *                 鍏朵腑hash绠楁硶鏍规嵁鎽樿鐗堟湰浣跨敤瀵瑰簲鐨勭畻娉曪紙濡俿ha1銆乵d5銆乻ha-256绛夛級銆�
+     * @param secretKey 骞冲彴鍒嗛厤缁欎笟鍔$郴缁熺殑绉侀挜
+     * @return
+     */
+    public static String buildSign(String algorithm,String appId,String timestamp,String nonce,String summary,String secretKey) {
+        if(StringUtil.isEmpty(algorithm) || StringUtil.isEmpty(appId)
+            ||StringUtil.isEmpty(timestamp)
+            ||StringUtil.isEmpty(nonce)) {
+            throw new RuntimeException("Sign parameters not allow null!");
+        }
+        if(!allowedAlgorithms.contains(algorithm)) {
+            throw new RuntimeException("UnSupport algorithm type!");
+        }
+        StringBuilder sb = new StringBuilder();
+        sb.append("sd-algorithm=").append(algorithm);
+        sb.append("&sd-appid=").append(appId);
+        sb.append("&sd-nonce=").append(nonce);
+        if(!StringUtil.isEmpty(summary)) {
+            sb.append("&sd-summary=").append(summary);
+        }
+        sb.append("&sd-timestamp=").append(timestamp);
+        sb.append("&key=").append(secretKey);
+        String stringSignTemp = sb.toString();
+        System.out.println("stringSignTemp:" + stringSignTemp);
+        System.out.println(stringSignTemp);
+        //sign
+        if(algorithm.equals(ALGORITHM_HMACSHA256)) {
+            try {
+                return hmac(secretKey,stringSignTemp,"HmacSHA256");
+            } catch (Exception e) {
+                e.printStackTrace();
+                return null;
+            }
+        } else {
+            try {
+                return sha(stringSignTemp,algorithm);
+            } catch (Exception e) {
+                e.printStackTrace();
+                return null;
+            }
+        }
+    }
+
+    /**
+     * 妫€鏌ョ鍚嶆槸鍚﹀悎娉�
+     * @param algorithm 绛惧悕绠楁硶銆係HA1,MD5锛孲HA-256,HMAC-SHA256
+     * @param appId 搴旂敤鏍囪瘑锛屾鏍囪瘑鏄彁鍓嶅垎閰嶇粰璋冪敤绯荤粺鐨�
+     * @param timestamp 鏃堕棿鎴炽€傞暱鏁存暟锛屾槸UNIX鏃堕棿鐨勬绉掓暟锛屽嵆浜х敓绛惧悕鏃剁殑鏃堕棿璺�1970骞�1鏈�1鏃ラ浂鏃剁殑姣鏁扮殑鍗佽繘鍒跺瓧绗︿覆銆�
+     *                  姝ゆ椂闂存埑浠h〃浜嗙鍚嶇殑鏃舵晥鎬э紝濡傛灉姝ゆ椂闂翠笌褰撳墠鏃堕棿宸ぇ浜庢煇涓€硷紙寤鸿涓嶈秴杩�20鍒嗛挓锛夋椂锛岀郴缁熻涓烘绛惧悕宸茬粡澶辨晥
+     * @param nonce 闅忔満鏁般€傜敤浜庡弬涓庣鍚嶈繍绠�
+     * @param summary  鎽樿锛屼笟鍔℃帴鍙e鍔犲瓧娈电殑hash鍊笺€傚弬涓庣鍚嶏紝杩涗竴姝ョ鍚嶇殑鍙傛暟鍊煎extraText=鈥渓oginName=0810035&userId=2鈥濓紝
+     *                 闇€瑕乭ash鍚庝紶杈擄紝涓氬姟绯荤粺鍦ㄦ牎楠宻ign鐨勫熀纭€涓婅繘涓€姝ユ牎楠屾鍊笺€俬ex锛坔ash锛坋xtraText锛夛級鍚庣殑鍐呭,
+     *                 鍏朵腑hash绠楁硶鏍规嵁鎽樿鐗堟湰浣跨敤瀵瑰簲鐨勭畻娉曪紙濡俿ha1銆乵d5銆乻ha-256绛夛級銆�
+     * @param secretKey 骞冲彴鍒嗛厤缁欎笟鍔$郴缁熺殑绉侀挜
+     * @param sign 闇€瑕佹牎楠岀殑绛惧悕
+     * @param signInvalidTime 绛惧悕鏈夋晥鏈� 鍗曚綅鍒嗛挓
+     * @return
+     */
+    public static boolean checkSign(String algorithm,String appId,String timestamp,String nonce,String summary,String secretKey,String sign,long signInvalidTime) {
+        //妫€鏌ョ鍚嶆椂闂存槸鍚﹁繃鏈�
+        long now = System.currentTimeMillis();
+        long timesta = Long.parseLong(timestamp);
+        if((now-timesta)>signInvalidTime*60*1000) {//绛惧悕鏈夋晥鏃堕棿 榛樿20鍒嗛挓
+            throw new RuntimeException( "绛惧悕宸插け鏁堬紒");
+        }
+        String buildSign = buildSign(algorithm, appId, timestamp, nonce, summary, secretKey);
+        if(!StringUtil.isEmpty(buildSign) && !StringUtil.isEmpty(sign) && buildSign.equals(sign)) {
+            return true;
+        }
+        return false;
+    }
+
+
+
+    /**
+     * 绛惧悕鎽樿
+     * @param algorithm hash绠楁硶 SHA1,MD5锛孲HA-256
+     * @param summaryText 鎽樿鍐呭
+     * @return
+     */
+    public static String buildSummary(String algorithm,String summaryText) {
+        try {
+            return sha(summaryText,algorithm);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 妫€鏌ユ憳瑕佺鍚�
+     * @param algorithm
+     * @param summaryText
+     * @param summarySign
+     * @return
+     */
+    public static boolean checkSummary(String algorithm,String summaryText,String summarySign) {
+        String sign = buildSummary(algorithm, summaryText);
+        if(!StringUtil.isEmpty(sign) && !StringUtil.isEmpty(summarySign) && summarySign.equals(sign)) {
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
+     * sha
+     * @param text
+     * @param signType
+     * @return
+     * @throws Exception
+     */
+    private static String sha(String text, String signType) throws Exception{
+        MessageDigest sha = MessageDigest.getInstance(signType);
+        byte[] digest = sha.digest(text.getBytes("UTF-8"));
+        return Hex.encodeHexString(digest).toUpperCase();
+    }
+
+    /**
+     * hmac
+     * @param accessSecret
+     * @param stringToSign
+     * @param singType
+     * @return
+     * @throws Exception
+     */
+    private static String hmac(String accessSecret,String stringToSign,String singType) throws Exception{
+        javax.crypto.Mac mac = javax.crypto.Mac.getInstance(singType);
+        mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), singType));
+        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
+        return Hex.encodeHexString(signData).toUpperCase();
+    }
+
+//    public static void main(String[] args) {
+//        String appId = "xgxt";
+//        String algorithm= "SHA1";
+//        String timestamp= System.currentTimeMillis() +"";
+//        String nonce= "ibuaiVcKdpRxkhJA";
+//        String summary= "loginName=zhangsan";
+//        String buildSummary = buildSummary(ALGORITHM_SHA1, summary);
+//        String key = "49123c3d-0d98-4ef5-8128-bdc5f98b3fbd";
+//        String sign = buildSign(algorithm,appId,timestamp,nonce,buildSummary,key);
+//        System.out.println(checkSign(algorithm,appId,timestamp,nonce,buildSummary,key,sign,20));
+//    }
+}
diff --git a/ServiceSite/src/main/java/com/seasky/flowportal/utils/Util.java b/ServiceSite/src/main/java/com/seasky/flowportal/utils/Util.java
new file mode 100644
index 0000000000000000000000000000000000000000..cfa3c43de98fc30b9d4243fcb6923f6c0ae90a48
--- /dev/null
+++ b/ServiceSite/src/main/java/com/seasky/flowportal/utils/Util.java
@@ -0,0 +1,91 @@
+package com.seasky.flowportal.utils;
+
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * 宸ュ叿绫�
+ */
+public class Util {
+    /**
+     * 瑙f瀽绛惧悕浜哄憳
+     * @param appCode
+     * @param secret
+     * @param timestamp
+     * @param nonce
+     * @return
+     * @throws Exception
+     */
+    public static String buildSignuate(String appCode, String secret, String timestamp, String nonce) throws Exception{
+        if (appCode == null) {
+            throw new Exception( "appCode锛�");
+        }
+        if (timestamp==null) {
+            throw new Exception( "timestamp瑙f瀽涓虹┖锛�");
+        }
+        if (nonce == null) {
+            throw new Exception( "nonce瑙f瀽涓虹┖锛�");
+        }
+        if (secret == null) {
+            throw new Exception( "绉侀挜閿欒锛�");
+        }
+        return  buildSignature(secret, timestamp, appCode, nonce);
+    }
+
+
+    public static String buildSignature(String securyKey, String timestamp, String openId, String nonce) throws Exception {
+        List<String> sParamList = new ArrayList<String>();
+        sParamList.add(securyKey);
+        sParamList.add(timestamp);
+        sParamList.add(nonce);
+        sParamList.add(openId);
+        Collections.sort(sParamList, new Comparator<String>() {
+            @Override
+            public int compare(String o1, String o2) {
+                return o1.compareTo(o2);
+            }
+        });
+        StringBuilder signature = new StringBuilder();
+        for (String sParam : sParamList) {
+            signature.append(sParam);
+        }
+        System.out.println("signature:"+signature);
+        MessageDigest md = MessageDigest.getInstance("SHA-1");
+        md.update(signature.toString().getBytes());
+        byte[] bytes = md.digest();
+//        System.out.println(toHex(bytes));
+//        System.out.println(bytesToHexStr(bytes));
+        return toHex(bytes);
+    }
+
+    private static String toHex(byte[] buffer) {
+        StringBuilder sb = new StringBuilder(buffer.length * 2);
+        for (int i = 0; i < buffer.length; i++) {
+            sb.append(Character.forDigit((buffer[i] & 240) >> 4, 16));
+            sb.append(Character.forDigit(buffer[i] & 15, 16));
+        }
+        return sb.toString();
+    }
+
+    private static String bytesToHexStr(byte[] bytes){
+        if(bytes == null){
+            return null;
+        }
+        StringBuffer sb = new StringBuffer();
+        StringBuffer sb2 = new StringBuffer();
+        String strInt = "";
+        for(int i=0;i<bytes.length;i++){
+            sb2.append(bytes[i]);
+            strInt = Integer.toHexString(bytes[i]&0xFF);
+            if(strInt.length()<2){
+                sb.append(0);
+            }
+            sb.append(strInt.toLowerCase());
+        }
+        System.out.println(sb2);
+        return sb.toString();
+    }
+}
diff --git a/ServiceSite/src/main/resources/application.properties b/ServiceSite/src/main/resources/application.properties
index d3bc73cf372f01d4ec1b04d28a6ae0d5fd520926..287db79d7620135890f1a77e998a66cdcbd2483a 100644
--- a/ServiceSite/src/main/resources/application.properties
+++ b/ServiceSite/src/main/resources/application.properties
@@ -18,6 +18,12 @@ seasky.redislockExpire=300
 seasky.projectVersion=1.0.0
 seasky.cacheName=redis
 
+spring.rabbitmq.host=demo.seaskysh.com
+spring.rabbitmq.port=5672
+spring.rabbitmq.virtual-host=bus_flow
+spring.rabbitmq.username=admin
+spring.rabbitmq.password=seasky$2020
+
 
 # \uFFFD\uFFFD\uFFFD\uFFFD DruidStatViewServlet
 #spring.datasource.druid.stat-view-servlet.enabled=true