diff --git a/server/api/v1/wk_process.go b/server/api/v1/wk_process.go index 96fe09a77f4b6420f05675346a5592aacf5e3286..d767579ebe7b2c82afa6207a21d5aec528146f74 100644 --- a/server/api/v1/wk_process.go +++ b/server/api/v1/wk_process.go @@ -2,6 +2,7 @@ package v1 import ( "fmt" + "gin-vue-admin/global" "gin-vue-admin/model" "gin-vue-admin/model/request" "gin-vue-admin/model/response" @@ -146,3 +147,70 @@ func GetWorkflowProcessList(c *gin.Context) { }, c) } } + +// @Tags WorkflowProcess +// @Summary 开启工作流 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}" +// @Router /workflowProcess/startWorkflow [post] +func StartWorkflow(c *gin.Context) { + business := c.Query("businessType") + wfInfo := model.WorkflowBusinessStruct[business]() + c.ShouldBindJSON(wfInfo) + err := service.StartWorkflow(wfInfo) + if err != nil { + response.FailWithMessage(err.Error(), c) + return + } + response.OkWithMessage("启动成功", c) +} + +// @Tags WorkflowProcess +// @Summary 我发起的工作流 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}" +// @Router /workflowProcess/getMyStated [get] +func GetMyStated(c *gin.Context) { + if claims, exists := c.Get("claims"); !exists { + errStr := "从Gin的Context中获取从jwt解析出来的用户ID失败, 请检查路由是否使用jwt中间件" + global.GVA_LOG.Error(errStr) + response.FailWithMessage(errStr, c) + } else { + waitUse := claims.(*request.CustomClaims) + err, wfms := service.GetMyStated(waitUse.ID) + if err != nil { + errStr := err.Error() + global.GVA_LOG.Error(errStr) + response.FailWithMessage(errStr, c) + } + response.OkWithData(gin.H{"wfms": wfms}, c) + } +} + +// @Tags WorkflowProcess +// @Summary 我的待办 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}" +// @Router /workflowProcess/getMyNeed [get] +func GetMyNeed(c *gin.Context) { + if claims, exists := c.Get("claims"); !exists { + errStr := "从Gin的Context中获取从jwt解析出来的用户ID失败, 请检查路由是否使用jwt中间件" + global.GVA_LOG.Error(errStr) + response.FailWithMessage(errStr, c) + } else { + waitUse := claims.(*request.CustomClaims) + err, wfms := service.GetMyNeed(waitUse.ID, waitUse.AuthorityId) + if err != nil { + errStr := err.Error() + global.GVA_LOG.Error(errStr) + response.FailWithMessage(errStr, c) + } + response.OkWithData(gin.H{"wfms": wfms}, c) + } +} diff --git a/server/cmd/datas/apis.go b/server/cmd/datas/apis.go index 17c630407327bc3fdba4c9ccf86f94e09e9a9ed0..a557a43e28b393fcb561a944c42884ad3bd605e2 100644 --- a/server/cmd/datas/apis.go +++ b/server/cmd/datas/apis.go @@ -83,6 +83,9 @@ var Apis = []model.SysApi{ {global.GVA_MODEL{ID: 72, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/findWorkflowProcess", "根据ID获取工作流", "workflowProcess", "GET"}, {global.GVA_MODEL{ID: 73, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/getWorkflowProcessList", "获取工作流", "workflowProcess", "GET"}, {global.GVA_MODEL{ID: 74, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/findWorkflowStep", "获取工作流步骤", "workflowProcess", "GET"}, + {global.GVA_MODEL{ID: 75, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/startWorkflow", "启动工作流", "workflowProcess", "POST"}, + {global.GVA_MODEL{ID: 76, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/getMyStated", "获取我发起的工作流", "workflowProcess", "GET"}, + {global.GVA_MODEL{ID: 77, CreatedAt: time.Now(), UpdatedAt: time.Now()}, "/workflowProcess/GetMyNeed", "获取我的待办", "workflowProcess", "GET"}, } func InitSysApi(db *gorm.DB) (err error) { diff --git a/server/cmd/datas/authority_menus.go b/server/cmd/datas/authority_menus.go index c2e845580bdc8a4b0b3b548c75ad35d19894f5b5..5a3189f8df67e71108d68166379221c6e422f5d2 100644 --- a/server/cmd/datas/authority_menus.go +++ b/server/cmd/datas/authority_menus.go @@ -42,6 +42,8 @@ var AuthorityMenus = []SysAuthorityMenus{ {"888", 29}, {"888", 30}, {"888", 31}, + {"888", 32}, + {"888", 33}, {"8881", 1}, {"8881", 2}, {"8881", 8}, diff --git a/server/cmd/datas/casbins.go b/server/cmd/datas/casbins.go index 9135daa3c5f3a9dacbef4d2e2803666c706517c8..0e974d96b6f5c388fd4ca3a2fb3b6df48dd081ec 100644 --- a/server/cmd/datas/casbins.go +++ b/server/cmd/datas/casbins.go @@ -81,6 +81,9 @@ var Carbines = []gormadapter.CasbinRule{ {PType: "p", V0: "888", V1: "/workflowProcess/findWorkflowProcess", V2: "GET"}, {PType: "p", V0: "888", V1: "/workflowProcess/getWorkflowProcessList", V2: "GET"}, {PType: "p", V0: "888", V1: "/workflowProcess/findWorkflowStep", V2: "GET"}, + {PType: "p", V0: "888", V1: "/workflowProcess/startWorkflow", V2: "POST"}, + {PType: "p", V0: "888", V1: "/workflowProcess/getMyStated", V2: "GET"}, + {PType: "p", V0: "888", V1: "/workflowProcess/GetMyNeed", V2: "GET"}, {PType: "p", V0: "8881", V1: "/base/login", V2: "POST"}, {PType: "p", V0: "8881", V1: "/user/register", V2: "POST"}, {PType: "p", V0: "8881", V1: "/api/createApi", V2: "POST"}, diff --git a/server/cmd/datas/menus.go b/server/cmd/datas/menus.go index 3739401c6d9d9b7b1757dc9ac63e3f4448ee009f..5bc6e0f636446b5357158fb28e44b605a65ce343 100644 --- a/server/cmd/datas/menus.go +++ b/server/cmd/datas/menus.go @@ -41,6 +41,8 @@ var BaseMenus = []model.SysBaseMenu{ {GVA_MODEL: global.GVA_MODEL{ID: 29, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "28", Path: "workflowCreate", Name: "workflowCreate", Hidden: false, Component: "view/workflow/workflowCreate/workflowCreate.vue", Sort: 0, Meta: model.Meta{Title: "工作流绘制", Icon: "circle-plus"}}, {GVA_MODEL: global.GVA_MODEL{ID: 30, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "28", Path: "workflowProcess", Name: "workflowProcess", Hidden: false, Component: "view/workflow/workflowProcess/workflowProcess.vue", Sort: 0, Meta: model.Meta{Title: "工作流列表", Icon: "s-cooperation"}}, {GVA_MODEL: global.GVA_MODEL{ID: 31, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "28", Path: "workflowUse", Name: "workflowUse", Hidden: true, Component: "view/workflow/workflowUse/workflowUse.vue", Sort: 0, Meta: model.Meta{Title: "使用工作流", Icon: "video-play"}}, + {GVA_MODEL: global.GVA_MODEL{ID: 32, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "28", Path: "started", Name: "started", Hidden: false, Component: "view/workflow/userList/started.vue", Sort: 0, Meta: model.Meta{Title: "我发起的", Icon: "s-order"}}, + {GVA_MODEL: global.GVA_MODEL{ID: 33, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "28", Path: "need", Name: "need", Hidden: false, Component: "view/workflow/userList/need.vue", Sort: 0, Meta: model.Meta{Title: "我的待办", Icon: "s-platform"}}, } func InitSysBaseMenus(db *gorm.DB) (err error) { diff --git a/server/core/server.go b/server/core/server.go index 3bbba3c4963a4c83bd96a682eb754ec08909e6df..cd77b1ed31eb4fd9460b6cbbe0761f6be1b7fcf3 100644 --- a/server/core/server.go +++ b/server/core/server.go @@ -17,6 +17,7 @@ func RunWindowsServer() { // 初始化redis服务 initialize.Redis() } + initialize.InitWkMode() Router := initialize.Routers() Router.Static("/form-generator", "./resource/page") diff --git a/server/go.mod b/server/go.mod index 230164e23cf6b53e864db01ec0e09c65eeb61eb3..358cc460c5ba70314ec39d9a5d8f3c7e95a01971 100644 --- a/server/go.mod +++ b/server/go.mod @@ -1,6 +1,6 @@ module gin-vue-admin -go 1.12 +go 1.14 require ( github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect diff --git a/server/initialize/gorm.go b/server/initialize/gorm.go index d09c77deacd36fde4dee124270a1ec26e96cb40d..90435837d992cfa34a136ae858a68c79e0820a2a 100644 --- a/server/initialize/gorm.go +++ b/server/initialize/gorm.go @@ -42,6 +42,8 @@ func MysqlTables(db *gorm.DB) { model.WorkflowEdge{}, model.WorkflowStartPoint{}, model.WorkflowEndPoint{}, + model.WorkflowMove{}, + model.ExaWfLeave{}, ) if err != nil { global.GVA_LOG.Error("register table failed", zap.Any("err", err)) diff --git a/server/initialize/router.go b/server/initialize/router.go index bd9079638ab8de9ffeec43396584bb8c0206eb07..f4b9397c22b4a677c7d7a8397bccedfd6dc5db3f 100644 --- a/server/initialize/router.go +++ b/server/initialize/router.go @@ -42,6 +42,7 @@ func Routers() *gin.Engine { router.InitSysOperationRecordRouter(ApiGroup) // 操作记录 router.InitEmailRouter(ApiGroup) // 邮件相关路由 router.InitWorkflowProcessRouter(ApiGroup) // 工作流创建相关接口 + router.InitExaWfLeaveRouter(ApiGroup) // 工作流创建相关接口 global.GVA_LOG.Info("router register success") return Router diff --git a/server/initialize/workflow.go b/server/initialize/workflow.go new file mode 100644 index 0000000000000000000000000000000000000000..d31751c98f03eacdd56121e7733d1b7a3cada884 --- /dev/null +++ b/server/initialize/workflow.go @@ -0,0 +1,22 @@ +package initialize + +import "gin-vue-admin/model" + +func initWkModel() { + model.WorkflowBusinessStruct = make(map[string]func() model.GVA_Workflow) + model.WorkflowBusinessStruct["leave"] = func() model.GVA_Workflow { + return new(model.ExaWfLeaveWorkflow) + } +} + +func initWkTable() { + + model.WorkflowBusinessTable = make(map[string]string) + model.WorkflowBusinessTable["leave"] = "exa_wf_leaves" +} + +func InitWkMode() { + initWkModel() + initWkTable() + +} diff --git a/server/model/exa_wf_leave.go b/server/model/exa_wf_leave.go new file mode 100644 index 0000000000000000000000000000000000000000..cb6fe65adda8671c434dafb7a084891facb44ac3 --- /dev/null +++ b/server/model/exa_wf_leave.go @@ -0,0 +1,21 @@ +// 自动生成模板ExaWfLeave +package model + +import ( + "gin-vue-admin/global" + "time" +) + +// 如果含有time.Time 请自行import time包 +type ExaWfLeave struct { + global.GVA_MODEL + Cause string `json:"cause" form:"cause" gorm:"column:cause;comment:"` + StartTime time.Time `json:"startTime" form:"startTime" gorm:"column:start_time;comment:"` + EndTime time.Time `json:"endTime" form:"endTime" gorm:"column:end_time;comment:"` +} + +type ExaWfLeaveWorkflow struct { + // 工作流操作结构体 + WorkflowBase `json:"wf"` + ExaWfLeave `json:"business"` +} diff --git a/server/model/wf_process.go b/server/model/wf_process.go index 4ac13d34c7375accbd74fac14708b421e75f9a2a..6acf4a535e13f964181f9809ed5b03aab6201af5 100644 --- a/server/model/wf_process.go +++ b/server/model/wf_process.go @@ -6,24 +6,49 @@ import ( "time" ) +var WorkflowBusinessStruct map[string]func() GVA_Workflow +var WorkflowBusinessTable map[string]string type GVA_Workflow interface { - CreateWorkflow(WorkflowNode,GVA_Workflow) - GetBusinessType()string + GetTableName() string + CreateWorkflowMove() *WorkflowMove + GetBusinessType() string + GetWorkflowBase() WorkflowBase } -type WorkflowFunc struct { - BusinessType string +type WorkflowBase struct { + BusinessID uint `gorm:"<-:false;column:id"` // 业务对应ID(businessID)的返回 + BusinessType string `json:"businessType" gorm:"-"` + PromoterID uint `json:"promoterID" gorm:"-"` + WorkflowProcessID string `json:"workflowProcessID" gorm:"-"` + WorkflowNodeID string `json:"workflowNodeID" gorm:"-"` + Action string `json:"action" gorm:"-"` } -func(w *WorkflowFunc)CreateWorkflow(node WorkflowNode,businessModel GVA_Workflow){ - +func (w WorkflowBase) CreateWorkflowMove() (businessModel *WorkflowMove) { + return &WorkflowMove{ + BusinessType: w.BusinessType, + PromoterID: w.PromoterID, + WorkflowProcessID: w.WorkflowProcessID, + WorkflowNodeID: w.WorkflowNodeID, + BusinessID: w.BusinessID, + Action: w.Action, + IsActive: true, + } } -func(w *WorkflowFunc)GetBusinessType()(businessType string){ +func (w WorkflowBase) GetBusinessType() (businessType string) { return w.BusinessType } +func (w WorkflowBase) GetWorkflowBase() (workflowBase WorkflowBase) { + return w +} + +func (w WorkflowBase) GetTableName() string { + return WorkflowBusinessTable[w.BusinessType] +} + //定义clazz常量 const ( @@ -40,23 +65,16 @@ const ( PROCESS string = "process" ) -type WorkflowMove struct { +type WorkflowMove struct { global.GVA_MODEL WorkflowProcessID string `json:"workflowProcessID" gorm:"comment:工作流模板ID"` - BusinessType string `json:"businessType" gorm:"comment:业务标记"` - BusinessID uint `json:"businessID" gorm:"comment:业务ID"` - WorkflowMoveInfo []WorkflowMoveInfo `json:"workflowMoveInfo" gorm:"comment:当前流转详情"` - Promoter uint `json:"Promoter" gorm:"comment:当前流转发起人"` -} - - -type WorkflowMoveInfo struct { - global.GVA_MODEL - WorkflowMoveID uint `json:"workflowMoveID" gorm:"comment:关联WorkflowMove"` - WorkflowNodeID string `json:"workflowNodeID" gorm:"comment:流程节点ID"` - Params string `json:"params" gorm:"comment:流转参数"` - Description string `json:"description" gorm:"comment:流转说明"` - Status int `json:"status" gorm:"comment:流转状态(来自字典 0为进行中)"` + WorkflowNodeID string `json:"workflowNodeID" gorm:"comment:工作流节点ID"` + BusinessType string `json:"businessType" gorm:"comment:业务标记"` + BusinessID uint `json:"businessID" gorm:"comment:业务ID"` + PromoterID uint `json:"promoterID" gorm:"comment:当前流转发起人"` + Action string `json:"action" gorm:"comment:工作流驱动事件"` + Param string `json:"param" gorm:"comment:工作流驱动参数"` + IsActive bool `json:"isActive" gorm:"comment:是否是活跃节点 "` } type WorkflowProcess struct { @@ -80,7 +98,7 @@ type WorkflowNode struct { CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` - WorkflowProcessID string `json:"-" gorm:"comment:流程标识"` + WorkflowProcessID string `json:"workflowProcessID" gorm:"comment:流程标识"` Clazz string `json:"clazz" gorm:"comment:节点类型"` Label string `json:"label" gorm:"comment:节点名称"` Type string `json:"type" gorm:"comment:图标类型"` diff --git a/server/router/wk_process.go b/server/router/wk_process.go index 0200c877f8dd10ae39d0b67ae14fe07e2b7b31c3..76dd7f11228ecf3f718c25ec1f9e3e4e30155127 100644 --- a/server/router/wk_process.go +++ b/server/router/wk_process.go @@ -14,7 +14,10 @@ func InitWorkflowProcessRouter(Router *gin.RouterGroup) { WorkflowProcessRouter.DELETE("deleteWorkflowProcessByIds", v1.DeleteWorkflowProcessByIds) // 批量删除WorkflowProcess WorkflowProcessRouter.PUT("updateWorkflowProcess", v1.UpdateWorkflowProcess) // 更新WorkflowProcess WorkflowProcessRouter.GET("findWorkflowProcess", v1.FindWorkflowProcess) // 根据ID获取WorkflowProcess - WorkflowProcessRouter.GET("findWorkflowStep", v1.FindWorkflowStep) // 根据ID获取工作流步骤 + WorkflowProcessRouter.GET("findWorkflowStep", v1.FindWorkflowStep) // 根据ID获取工作流步骤 WorkflowProcessRouter.GET("getWorkflowProcessList", v1.GetWorkflowProcessList) // 获取WorkflowProcess列表 + WorkflowProcessRouter.POST("startWorkflow", v1.StartWorkflow) // 开启工作流 + WorkflowProcessRouter.GET("getMyStated", v1.GetMyStated) // 获取我发起的工作流 + WorkflowProcessRouter.GET("getMyNeed", v1.GetMyNeed) // 获取我的待办 } } diff --git a/server/service/wk_process.go b/server/service/wk_process.go index e4dd9fa64850a438b56ecdfdebbccbc74e111c5d..9993b63facfb2ba2675aa5f7d8fb75fa73a9ea0a 100644 --- a/server/service/wk_process.go +++ b/server/service/wk_process.go @@ -1,10 +1,12 @@ package service import ( + "errors" "gin-vue-admin/global" "gin-vue-admin/model" "gin-vue-admin/model/request" "gorm.io/gorm" + "strconv" ) //@author: [piexlmax](https://github.com/piexlmax) @@ -151,3 +153,127 @@ func GetWorkflowProcessInfoList(info request.WorkflowProcessSearch) (err error, err = db.Limit(limit).Offset(offset).Find(&workflowProcesss).Error return err, workflowProcesss, total } + +//@author: [piexlmax](https://github.com/piexlmax) +//@function: StartWorkflow +//@description: 开启一个工作流 +//@param: wfInterface model.GVA_Workflow +//@return: err error + +func StartWorkflow(wfInterface model.GVA_Workflow) (err error) { + err = global.GVA_DB.Transaction(func(tx *gorm.DB) error { + var txErr error + txErr = tx.Table(wfInterface.GetTableName()).Create(wfInterface).Error + if txErr != nil { + return txErr + } + wfm := wfInterface.CreateWorkflowMove() + txErr = tx.Create(wfm).Error + if txErr != nil { + return txErr + } + txErr = complete(tx, wfm) + if txErr != nil { + return txErr + } + return nil + }) + return err +} + +//func CompleteWorkflowNode(wfInterface model.GVA_Workflow)(err error){ +// +//} + +func complete(tx *gorm.DB, wfm *model.WorkflowMove) (err error) { + var returnWfm model.WorkflowMove + var nodeInfo model.WorkflowNode + var Edges []model.WorkflowEdge + txErr := tx.First(&returnWfm, "business_type = ? and business_id = ? and workflow_process_id = ? and workflow_node_id = ? and is_active = ?", wfm.BusinessType, wfm.BusinessID, wfm.WorkflowProcessID, wfm.WorkflowNodeID, true).Error + if txErr != nil { + return txErr + } + txErr = tx.First(&nodeInfo, "ID = ?", wfm.WorkflowNodeID).Error + if txErr != nil { + return txErr + } + + if nodeInfo.Clazz == model.START || nodeInfo.Clazz == model.USER_TASK { + txErr = tx.Find(&Edges, "workflow_process_id = ? and source = ?", wfm.WorkflowProcessID, wfm.WorkflowNodeID).Error + if txErr != nil { + return txErr + } + if len(Edges) == 0 { + return errors.New("不存在当前节点为起点的后续流程") + } + if len(Edges) == 1 { + //当前节点为初始节点时候 + if nodeInfo.Clazz == model.START { + txErr = tx.Where("id = ?", returnWfm.ID).First(&model.WorkflowMove{}).Update("is_active", false).Error + if txErr != nil { + return txErr + } + } + //当前节点为流转节点时候 + if nodeInfo.Clazz == model.USER_TASK { + txErr = tx.Where("id = ?", returnWfm.ID).First(&model.WorkflowMove{}).Update("action", "complete").Update("is_active", false).Error + if txErr != nil { + return txErr + } + } + + newWfm := createNewWorkflowMove(&returnWfm, Edges[0].Target) + txErr = tx.Create(newWfm).Error + if txErr != nil { + return txErr + } + // 当target为自动节点时候 需要做一些事情 这里暂时先不处理 后续慢慢完善 + } + if len(Edges) > 1 { + var needUseTargetNodeID string + txErr = tx.Where("id = ?", returnWfm.ID).Update("is_active", false).Error + if txErr != nil { + return txErr + } + for _, v := range Edges { + if v.ConditionExpression == wfm.Param { + needUseTargetNodeID = v.Target + break + } + } + newWfm := createNewWorkflowMove(&returnWfm, needUseTargetNodeID) + txErr = tx.Create(newWfm).Error + if txErr != nil { + return txErr + } + // 当target为自动节点时候 需要做一些事情 这里暂时先不处理 后续慢慢完善 + } + } else { + return errors.New("目前只支持start节点和userTask功能,其他功能正在开发中") + } + return nil +} + +func createNewWorkflowMove(oldWfm *model.WorkflowMove, targetNodeID string) (newWfm *model.WorkflowMove) { + return &model.WorkflowMove{ + BusinessID: oldWfm.BusinessID, + BusinessType: oldWfm.BusinessType, + PromoterID: oldWfm.PromoterID, + WorkflowNodeID: targetNodeID, + WorkflowProcessID: oldWfm.WorkflowProcessID, + Action: "", + IsActive: true, + } +} + +func GetMyStated(userID uint) (err error, wfms []model.WorkflowMove) { + err = global.GVA_DB.Find(&wfms, "promoter_id = ? and is_active", userID, true).Error + return err, wfms +} + +func GetMyNeed(userID uint, AuthorityID string) (err error, wfms []model.WorkflowMove) { + user := "%," + strconv.Itoa(int(userID)) + ",%" + auth := "%," + AuthorityID + ",%" + err = global.GVA_DB.Joins("INNER JOIN workflow_nodes as node ON workflow_moves.workflow_node_id = node.id").Where("(node.assign_type = ? AND node.assign_value LIKE ? ) OR (node.assign_type = ? AND node.assign_value LIKE ? )", "user", user, "authority", auth).Find(&wfms).Error + return err, wfms +} diff --git a/web/src/view/exa_wf_leave/exa_wf_leaveFrom.vue b/web/src/view/exa_wf_leave/exa_wf_leaveFrom.vue new file mode 100644 index 0000000000000000000000000000000000000000..db7ee58ec4035535bdaaf9174d4654dbfd384a71 --- /dev/null +++ b/web/src/view/exa_wf_leave/exa_wf_leaveFrom.vue @@ -0,0 +1,98 @@ + + + + + \ No newline at end of file diff --git a/web/src/view/workflow/workflowUse/workflowUse.vue b/web/src/view/workflow/workflowUse/workflowUse.vue index f6c207d998ac5095400ff25425984d9142cb00df..cc2077e77a65e4f1964d6ea8d027323a3fe89b92 100644 --- a/web/src/view/workflow/workflowUse/workflowUse.vue +++ b/web/src/view/workflow/workflowUse/workflowUse.vue @@ -1,6 +1,7 @@ \ No newline at end of file