最近在研究工單系統的時候,被我找到一個很是流弊的工單系統,咱們都知道工單系統最麻煩的就是流程和模版的維護,而且,在工單處理過程當中極可能會添加一些操做,這些操做被稱之爲鉤子。就按我目前調研的結果來講,目前其實沒有啥工單系統能實現的這麼好的。html
這個工單系統就把流程設計,模版設計等等作的很是不錯,並且對權限的把控很是詳細,包括API接口、菜單、頁面按鈕權限,均可以靈活的控制,很是的不錯。前端
Demo:http://fdevops.com:8001/#/dashboardvue
Github:https://github.com/lanyulei/ferrynode
若是以爲不錯就給做者一個star,你的star沒準就是做者繼續維護下去的動力呢。python
系統管理linux
流程中心nginx
等等還有不少功能待研究。git
對於一個完整的工做流系統來講,咱們須要有流程、模版、分組、用戶、任務等等,而且這些東西都是能夠靈活定製的,由於若是不能靈活定製的話,對於普通的使用這來講是很是不方便的,因此對於一個好的工做流系統,是必需要實現靈活性的。github
下面直接來展現一下,數據結構的設計圖。web
流程分類
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" }
go >= 1.14 vue >= 2.6 npm >= 6.14
二次開發
後端
# 1. 獲取代碼 git https://github.com/lanyulei/ferry.git # 2. 進入工做路徑 cd ./ferry # 3. 修改配置 ferry/config/settings.dev.yml vi ferry/config/settings.dev.yml # 配置信息注意事項: 1. 程序的啓動參數 2. 數據庫的相關信息 3. 日誌的路徑 # 4. 初始化數據庫 go run main.go init -c=config/settings.dev.yml # 5. 啓動程序 go run main.go server -c=config/settings.dev.yml
前端
# 1. 獲取代碼 git https://github.com/lanyulei/ferry_web.git # 2. 進入工做路徑 cd ./ferry_web # 3. 安裝依賴 npm install # 4. 啓動程序 npm run dev
上線部署
後端
# 1. 進入到項目路徑下進行交叉編譯(centos) env GOOS=linux GOARCH=amd64 go build 更多交叉編譯內容,請訪問 https://www.fdevops.com/2020/03/08/go-locale-configuration # 2. config目錄上傳到項目根路徑下,並確認配置信息是否正確 vi ferry/config/settings.yml # 配置信息注意事項: 1. 程序的啓動參數 2. 數據庫的相關信息 3. 日誌的路徑 # 3. 建立日誌路徑及靜態文件經歷 mkdir -p log static/uploadfile # 4. 初始化數據 ./ferry init -c=config/settings.yml # 5. 啓動程序,推薦經過"進程管理工具"進行啓動維護 nohup ./ferry server -c=config/settings.yml > /dev/null 2>&1 &
前端
# 1. 編譯 npm run build:prod # 2. 將dist目錄上傳至項目路徑下便可。 mv dist web # 3. nginx配置,根據業務自行調整便可 server { listen 8001; # 監聽端口 server_name localhost; # 域名能夠有多個,用空格隔開 #charset koi8-r; #access_log logs/host.access.log main; location / { root /data/ferry/web; index index.html index.htm; #目錄內的默認打開文件,若是沒有匹配到index.html,則搜索index.htm,依次類推 } #ssl配置省略 location /api { # rewrite ^.+api/?(.*)$ /$1 break; proxy_pass http://127.0.0.1:8002; #node api server 即須要代理的IP地址 proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 登錄 location /login { proxy_pass http://127.0.0.1:8002; #node api server 即須要代理的IP地址 } # 刷新token location /refresh_token { proxy_pass http://127.0.0.1:8002; #node api server 即須要代理的IP地址 } # 接口地址 location /swagger { proxy_pass http://127.0.0.1:8002; #node api server 即須要代理的IP地址 } # 後端靜態文件路徑 location /static/uploadfile { proxy_pass http://127.0.0.1:8002; #node api server 即須要代理的IP地址 } #error_page 404 /404.html; #對錯誤頁面404.html 作了定向配置 # redirect server error pages to the static page /50x.html #將服務器錯誤頁面重定向到靜態頁面/50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }