从设计到开发,实现一个人人都可以简单使用及管理的工作流系统

2020-07-24 13:58:55 +08:00
 lanyulei

工作流介绍

工作流( Workflow )就是工作流程的计算模型,即将工作流程中的工作如何前后组织在一起的逻辑和规则在计算机中以恰当的模型进行表示并对其实施计算。

工作流在 IT 领域不算是“新人”了,工作流思想在上世纪 60 年代就有人提出过; 70 年代就有人开始尝试,但是由于当时许多的限制,工作流一直没有成功的被实现; 80 年代才出现第一批成功的工作流系统; 90 年代工作流技术走向了第一个发展高峰期; 90 年代后至今工作流出现了很多版本,但是主旨还是不变的,为了使我们的工作变得更加高效。

我们通过工作流可以节省很多不必要的时间,预设置好的处理人,可以让我们不必反复的问别人谁负责此节点;通过任务来实现最后的操作,可以让我们减少很多人力成本,当然想要实现一套完善、简单、通用、方便管理的工作流系统也是非常不容易的,接下来推荐一个较为通用的,方便使用及管理的工作流系统。

Demo: 工作流系统( ferry )

Github: https://github.com/lanyulei/ferry

项目问答社区: 问答社区

此工作流系统使用的技术栈:

数据结构设计

对于一个完整的工作流系统来说,我们需要有流程、模版、分组、用户、任务等等,并且这些东西都是可以灵活定制的,因为如果不能灵活定制的话,对于普通的使用这来说是非常不方便的,所以对于一个好的工作流系统,是必须要实现灵活性的。

下面直接来展示一下,数据结构的设计图。

接下来对各个表进行详细的介绍,这里仅仅是中文介绍,至于数据库的表名,可自行定义:

| 表 | 介绍 | | -------- | -------- | | 用户管理 | 这个是一个用户管理的综合,包括(用户管理,用户组管理,部门管理,权限管理) | | 流程分类 | 只为区分各个功能的流程 | | 流程 | 管理流程信息,对节点、流转、分类等数据的管理及维护 | | 模版 | 保存我们自定义设置的模版,方便在创建或处理流程的时候渲染表单 | | 工单 | 记录每次提交的流程申请 | | 工单绑定模版 | 绑定模版并且记录每次流程申请对应的申请数据 | | 工单流转历史 | 记录流程申请的每一次的处理结果 | | 任务 | 每个节点及流程结束后需要执行的任务,可选项 | | 任务执行历史 | 记录每次任务执行的历史并保存执行结果 |

流程分类

type Classify struct {
	base.Model
	Name    string `gorm:"column:name; type: varchar(128)" json:"name" form:"name"`     // 分类名称
	Creator int    `gorm:"column:creator; type: int(11)" json:"creator" form:"creator"` // 创建者
}

func (Classify) TableName() string {
	return "process_classify"
}

流程

type Info struct {
	base.Model
	Name      string          `gorm:"column:name; type:varchar(128)" json:"name" form:"name"`        // 流程名称
	Structure json.RawMessage `gorm:"column:structure; type:json" json:"structure" form:"structure"` // 流程结构
	Classify  int             `gorm:"column:classify; type:int(11)" json:"classify" form:"classify"` // 分类 ID
	Tpls      json.RawMessage `gorm:"column:tpls; type:json" json:"tpls" form:"tpls"`                // 模版
	Task      json.RawMessage `gorm:"column:task; type:json" json:"task" form:"task"`                // 任务 ID, array, 可执行多个任务,可以当成通知任务,每个节点都会去执行
	Creator   int             `gorm:"column:creator; type:int(11)" json:"creator" form:"creator"`    // 创建者
}

func (Info) TableName() string {
	return "process_info"
}

模版

type Info struct {
	base.Model
	Name          string          `gorm:"column:name; type: varchar(128)" json:"name" form:"name" binding:"required"`                       // 模板名称
	FormStructure json.RawMessage `gorm:"column:form_structure; type: json" json:"form_structure" form:"form_structure" binding:"required"` // 表单结构
	Creator       int             `gorm:"column:creator; type: int(11)" json:"creator" form:"creator"`                                      // 创建者
	Remarks       string          `gorm:"column:remarks; type: longtext" json:"remarks" form:"remarks"`                                     // 备注
}

func (Info) TableName() string {
	return "tpl_info"
}

工单

type Info struct {
	base.Model
	Title         string          `gorm:"column:title; type:varchar(128)" json:"title" form:"title"`                    // 工单标题
	Process       int             `gorm:"column:process; type:int(11)" json:"process" form:"process"`                   // 流程 ID
	Classify      int             `gorm:"column:classify; type:int(11)" json:"classify" form:"classify"`                // 分类 ID
	IsEnd         int             `gorm:"column:is_end; type:int(11); default:0" json:"is_end" form:"is_end"`           // 是否结束,0 未结束,1 已结束
	State         json.RawMessage `gorm:"column:state; type:json" json:"state" form:"state"`                            // 状态信息
	RelatedPerson json.RawMessage `gorm:"column:related_person; type:json" json:"related_person" form:"related_person"` // 工单所有处理人
	Creator       int             `gorm:"column:creator; type:int(11)" json:"creator" form:"creator"`                   // 创建人
}

func (Info) TableName() string {
	return "work_order_info"
}

工单绑定模版

type TplData struct {
	base.Model
	WorkOrder     int             `gorm:"column:work_order; type: int(11)" json:"work_order" form:"work_order"`          // 工单 ID
	FormStructure json.RawMessage `gorm:"column:form_structure; type: json" json:"form_structure" form:"form_structure"` // 表单结构
	FormData      json.RawMessage `gorm:"column:form_data; type: json" json:"form_data" form:"form_data"`                // 表单数据
}

func (TplData) TableName() string {
	return "work_order_tpl_data"
}

工单流转历史

type CirculationHistory struct {
	base.Model
	Title        string `gorm:"column:title; type: varchar(128)" json:"title" form:"title"`                         // 工单标题
	WorkOrder    int    `gorm:"column:work_order; type: int(11)" json:"work_order" form:"work_order"`               // 工单 ID
	State        string `gorm:"column:state; type: varchar(128)" json:"state" form:"state"`                         // 工单状态
	Source       string `gorm:"column:source; type: varchar(128)" json:"source" form:"source"`                      // 源节点 ID
	Target       string `gorm:"column:target; type: varchar(128)" json:"target" form:"target"`                      // 目标节点 ID
	Circulation  string `gorm:"column:circulation; type: varchar(128)" json:"circulation" form:"circulation"`       // 流转 ID
	Processor    string `gorm:"column:processor; type: varchar(45)" json:"processor" form:"processor"`              // 处理人
	ProcessorId  int    `gorm:"column:processor_id; type: int(11)" json:"processor_id" form:"processor_id"`         // 处理人 ID
	CostDuration string `gorm:"column:cost_duration; type: varchar(128)" json:"cost_duration" form:"cost_duration"` // 处理时长
	Remarks      string `gorm:"column:remarks; type: longtext" json:"remarks" form:"remarks"`                       // 备注
}

func (CirculationHistory) TableName() string {
	return "work_order_circulation_history"
}

任务

type Info struct {
	base.Model
	Name     string `gorm:"column:name; type: varchar(256)" json:"name" form:"name"`               // 任务名称
	TaskType string `gorm:"column:task_type; type: varchar(45)" json:"task_type" form:"task_type"` // 任务类型
	Content  string `gorm:"column:content; type: longtext" json:"content" form:"content"`          // 任务内容
	Creator  int    `gorm:"column:creator; type: int(11)" json:"creator" form:"creator"`           // 创建者
	Remarks  string `gorm:"column:remarks; type: longtext" json:"remarks" form:"remarks"`          // 备注
}

func (Info) TableName() string {
	return "task_info"
}

任务执行历史

type History struct {
	base.Model
	Task          int    `gorm:"column:task; type: int(11)" json:"task" form:"task"`                                    // 任务 ID
	Name          string `gorm:"column:name; type: varchar(256)" json:"name" form:"name"`                               // 任务名称
	TaskType      int    `gorm:"column:task_type; type: int(11)" json:"task_type" form:"task_type"`                     // 任务类型, python, shell
	ExecutionTime string `gorm:"column:execution_time; type: varchar(128)" json:"execution_time" form:"execution_time"` // 执行时间
	Result        string `gorm:"column:result; type: longtext" json:"result" form:"result"`                             // 任务返回
}

func (History) TableName() string {
	return "task_history"
}

管理及使用介绍

流程管理

非常简单的就可以创建流程,拖拽一下,链接一下对应的节点,填充一下节点及流转对应的右边的数据,就可以完美的创建一条流程数据。通过这条流程,我们就可以去进行流程申请了。

表单设计

能够自定义表单对于一个工作流系统来说,是非常重要的。因为这样,就可以非常方便的管理用户的输入数据是啥。同时也能非常方便的来控制用户的输入。同时对于工作流管理这来说,大大的节省了表单维护的时间。

此次我们主要是介绍了一下数据结构的设计及代码的演示。同时也展示了一下数据在工作流开发中,比较复杂,但是对于用户体验来说很好的两个功能,一个是流程管理,一个是表单设计。

1441 次点击
所在节点    问与答
3 条回复
pwli
2020-07-24 14:47:55 +08:00
最近可能有类似需求,但没做过这方面的业务,请教楼主工作流设计这块儿有什么资料分享吗
vazo
2020-07-24 14:57:54 +08:00
nice😉
lanyulei
2020-08-19 18:08:25 +08:00
@pwli 欢迎加群撩。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/692796

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX