php开发业务工作流的设计小结
业务部门电脑维修网希望现有业务系统可以改造成类似OA那样的流程定制化,当时对系统的代码逻辑已有一定了解, 存在下面的一些问题
系统有两张与工作流相关的表,却并没有实现一个流程引擎来统管流程的走向,代码内直接粗暴的用id值判断流程,流程节点也是直接手写sql写进数据库.
流程相关的逻辑凌乱,代码冗余很多
耦合度很高,代码几乎都是一次性的,无法被他处调用
流程逻辑与业务逻辑混在一起, 新写一个业务需求时往往要花一定精力是书写流程相关的逻辑.
针对现实情况,大概有了如下目标
流程要可配置,每个流程节点有其固定的key来标识它,包括每个节点的处理结果
实现一个流程引擎来统一管理流程
每个节点有与之对应的处理类
因为部分节点的跳转并无特殊逻辑,应该有一个默认的节点处理类,它只有保存数据和提交流程结果的逻辑
在流程引擎处对每个节点的处理过程预埋几个钩子,这样要加入三方逻辑时就不必改动现有的文件
百度了几次,选定了jsPlumb这款插件,结合bootstrap、artTemplate最终实现了如下流程可视化效果:
img1
img2
img3
提交的数据格式如下:
{ "orkflo_group":"normal", "conf":{ "node_1":{ "name":"节点一","key":"node_1","orkflo_group":"normal", "status":{ "pass":{"key":"pass","name":"通过","apply_step":"2","next_orkflo_key":"node_2"}, "visit":{"key":"visit","name":"考察","apply_step":"2","next_orkflo_key":"node_3"}
}, "style":{"left":"407px","":"354px"}
}, "node_2":{ "name":"节点二","key":"node_2","orkflo_group":"normal", "status":{ "pass":{"key":"pass","name":"通过","apply_step":"3","next_orkflo_key":"node_4"}
}, "style":{"left":"609px","":"356px"}
}, "node_3":{ "name":"节点三","key":"node_3","orkflo_group":"normal", "status":{ "back":{"key":"back","name":"退回","apply_step":"99","next_orkflo_key":"node_1"}, "pass":{"key":"pass","name":"通过","apply_step":"","next_orkflo_key":"node_2"}
}, "style":{"left":"513px","":"501px"}
}, "node_4":{ "name":"节点四","key":"node_4","orkflo_group":"normal", "status":{ "back":{"key":"back","name":"退回","apply_step":"2","next_orkflo_key":"node_3"}, "pass":{"key":"pass","name":"通过","apply_step":"4","next_orkflo_key":"apply_end"}
}, "style":{"left":"816px","":"359px"}
}, "apply_end":{ "name":"业务结束","key":"apply_end","orkflo_group":"normal", "status":{}, "style":{"left":"781px","":"551px"}
}
}
}数据表部分三张流程相关的表,一张定义流程组,一张定义流程组的节点,一张定义节点可选的结果
CREATE TABLE `orkflo_group` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '0:监听流程组', `group_name` varchar(20) NOT NULL COMMENT '流程组名', `group_key` varchar(20) NOT NULL COMMENT '流程组标识', `enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否可用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='流程组表';CREATE TABLE `orkflo_node` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `orkflo_group_id` int(11) unsigned NOT NULL COMMENT '流程组ID,0:监听流程组', `node_name` varchar(20) NOT NULL COMMENT '节点名称', `node_key` varchar(20) NOT NULL COMMENT '流程节点标识', `is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否被删除', `style` varchar(255) DEFAULT NULL COMMENT '节点样式', PRIMARY KEY (`id`), UNIQUE KEY `orkflo_group_id` (`orkflo_group_id`,`node_key`), CONSTRAINT `orkflo_node_ibfk_1` FOREIGN KEY (`orkflo_group_id`) REFERENCES `orkflo_group` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='流程节点表';CREATE TABLE `orkflo_result` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `orkflo_node_id` int(11) unsigned NOT NULL COMMENT '所属工作流节点ID', `result_name` varchar(20) NOT NULL COMMENT '结论名称', `result_key` varchar(20) NOT NULL COMMENT '结论标识', `is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否被删除', `next_node_id` int(11) DEFAULT NULL COMMENT '下一个流程', `next_node_key` varchar(20) NOT NULL DEFAULT '' COMMENT '下一个流程标识' PRIMARY KEY (`id`), UNIQUE KEY `orkflo_id` (`orkflo_node_id`,`result_key`), CONSTRAINT `orkflo_result_ibfk_1` FOREIGN KEY (`orkflo_node_id`) REFERENCES `orkflo_node` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='流程节点结论表';流程引擎部分
定义了4个核心文件如下:
Workflo.class.php final类
核心方法如下:
public function getConf($orkflo_group){} //获取配置public function setConf($conf,$orkflo_group){} //设置配置public function getNodeResults($orkflo_key,$orkflo_group){} //获取节点结果集public function getListClass($orkflo_key, $uid){}//获取节点列表处理类public function getCommitClass($id, $orkflo_key, $uid){}//获取节点提交处理类WorkfloCommit.class.php abstract类
每个节点处理类都继承于这个抽象类,要实现如下两个抽象方法:
// 提交处理abstract protected function _mit($resultKey, array $data);// 页面输出显示abstract protected function _output($id);
WorkfloHook.class.php abstract类
每个节点的钩子文件都继承于这个类WorkfloList.class.php abstract类
列表类,主要有以下方法:
public function getTpl(){} // 获取列表模板public function getMod(){} // 获取列表模型public function listFilter(array &$list){} // 列表数据过滤public function setVars(){} // 设置模板变量可以定义一个空类继承它,作为默认列表类,特殊节点则定义节点列表类继承它覆盖相关方法(基本上只用默认类就可以了)
写的比较粗略, 不附带具体代码. 下面是最终流程配置的一个截图:
img4
作者sha_cq
链接https://.jianshu./p/e66de4c91a92
空调维修
- 我的世界电脑版运行身份怎么弄出来(我的世界
- 空调抽湿是什么意思,设置抽湿的温度有什么意
- 方太燃气灶有一个打不着火 怎么修复与排查方法
- 夏季免费清洗汽车空调的宣传口号
- 清洗完空调后出现漏水现象
- iphone6能玩什么游戏(iphone6游戏)
- 如何设置电脑密码锁屏(如何设置电脑密码锁屏
- win10删除开机密码提示不符合密码策略要求
- 电脑w7显示不是正版(w7不是正版怎么解决)
- 万家乐z8热水器显示e7解决 怎么修复与排查方法
- 1匹空调多少瓦数(1匹空调多少瓦)
- 安卓手机连接电脑用什么软件好(关于安卓手机
- 电脑网页看视频卡是什么原因(爱拍看视频卡)
- 华帝燃气灶点火器一直响然后熄火怎么办:问题
- 电脑壁纸怎么换(关于电脑壁纸怎么换的介绍)
- 冬天空调的出风口应该朝什么方向(冬天空调风