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

工作流介绍

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

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

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

Demo: 工作流系统(ferry)

项目问答社区: 问答社区

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

  • Golang
  • Gin
  • Gorm
  • Vue
  • Element

数据结构设计

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

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

工作流数据结构设计图

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

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

流程分类

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"
}

管理及使用介绍

流程管理

流程管理

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

表单设计

表单设计

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342