序言
感谢赞助我们服务器的朋友,目前服务器已购买,演示网站
http://tpflow.cojz8.com 欢迎测试。
文档支持免费下载,请加群; 如您购买本文档,感谢您的赞助支持。
交流群:532797225
什么是工作流?
工作流(Workflow),指“业务过程的部分或整体在计算机应用环境下的自动化”。简单的来说,类似工厂的流水线,A工作做完,到B工作,再到C工作,而中间可能需要一条输送带,联动整个生产,那么这可以称作是工作流。
什么是TpFlow
TpFlow(thinkphp work flow),作者比较懒而已简写了一点。
原归正传,TpFlow是用来解决OA、ERP、CRM、CMS等等办公软件的审核审批的问题。
最重要的是什么?
完全开源免费,你可以用于你的任何一个项目,你可以自行修改,无需作者授权。
既然是解决问题,好处在哪?
工作流可视化设计
工作流驱动及统一管理
不要在写IF SWITCH 各种判断,各种纠结
两句话即可与现有程序对接
来看看两句话怎么写?
调用工作流控制器,返回当前流程的审批状态
{:action('flow/status',['status'=>$k.status])}
调用工作流控制器,获取当前是发起状态/审批状态/权限审核
{:action('flow/btn',['wf_fid'=>$k.id,'wf_type'=>'news','status'=>$k.status])}
可以参考:详见:tpflow\application\index\view\news\index.html 新闻模块调用
关于TpFlow 开发团队及由来
这个以后再说。
交流群:532797225
作 者: QQ:1838188896
贡献者:QQ:2588234 上海东为信息科技有限公司鸣谢
感谢前端UI框架:HUI
感谢leipi流程设计器的思路及部分前端代码;
感谢phpworkflow 给的流程设计思路基础
如果你已经会使用Tp5、Git、Composer你可以跳过本章节
特别提示,需要有TP5.1的开发经验入门最快!
使用基础
Tpflow基于Tp5.1.7开发,所以你最少是会使用Thinkphp5的程序猿,如果这都不会,推荐以下:
然后你还要回基本的Git语句,如:
git clone https://gitee.com/ntdgg/tpflow
git add -A git commit -m 'Tpflow'; git push origin matster
git pull
当然过段时间我们会放在composer 你还需要掌握这个基本的。
安装
跟ThinkPhp一样不存在真正意义上的安装,就是使用GIT下载下载即可。
代码获取
作为一个程序员,你怎么能每次都想着ZIP、RAR下载
码云获取:码云地址
目录结构
Thinkphp5的目录结构
www WEB部署目录(或者子目录) ├─application 应用目录 ├─config 应用配置目录 ├─route 路由定义目录 ├─public WEB目录(对外访问目录) │ ├─static 工作流目录 │ ├─work 工作流目录 ├─thinkphp 框架系统目录 ├─extend 扩展类库目录 │ ├─workflow 工作流目录 ├─vendor 第三方类库目录(Composer依赖库) ├─build.php 自动生成定义文件(参考) ├─composer.json composer 定义文件 ├─LICENSE.txt 授权说明文件 ├─README.md README 文件 ├─think 命令行入口文件
\extend\workflow 为插件目录
├─workflow 扩展类库目录 │ ├─class 流引擎目录 │ ├─config 配置项目录 │ ├─db 数据操作目录 │ ├─msg 消息处理目录 │─workflow.php 工作流
├─Index\Controller 模块目录 │ ├─Flow.php 工作流引擎 │ ├─Flowdesign.php 工作流设计器
开始使用
复制 Index\Controller 目录下的 Flow.php Flowdesign.php 及对应的视图文件; 复制 extend 目录的 workflow 到你的目录 原则上已经可以正常使用工作流了,但这需要的你数据表设计规范(如表注释,数据字段注释等等)
部分使用代码
/*发起流程,选择工作流*/ public function start() { $wf_type = input('wf_type'); $info = ['wf_type'=>input('wf_type'),'wf_title'=>input('wf_title'),'wf_fid'=>input('wf_fid')]; $workflow = new workflow(); $flow = $workflow->getWorkFlow($wf_type); $this->assign('flow',$flow); $this->assign('info',$info); return $this->fetch(); } public function do_check() { $wf_fid = input('wf_fid'); $wf_type = input('wf_type'); $info = ['wf_title'=>input('wf_title'),'wf_fid'=>$wf_fid,'wf_type'=>$wf_type]; $workflow = new workflow(); $flowinfo = $workflow->workflowInfo($wf_fid,$wf_type); $this->assign('info',$info); $this->assign('flowinfo',$flowinfo); return $this->fetch(); }
后续章节收费特别说明:作者不差8.8元,只是为了开通一个服务器,来部署工作流用于在线演示,同时也给予我们一定的支持,不断完善该插件,若您看不惯, 大可不读,感谢您。
工作流设计
工作流的流程示意图
![]()
工作流引擎工作示意图
工作流设计样例
流程设计
当你安装完成的时候,你将看到如下界面,当然这是实例教程。
系统后期的升级,可能会略有不同。
- 点击模拟登入[当然部署上你的项目,就不是模拟登入了]
- 点击流程设计按钮
- 添加一个流程,
流程类型>这里展示的**流程类型**对应的是你数据库里的表 >select TABLE_NAME,TABLE_COMMENT from information_schema.tables where table_schema='tpflow' and table_type='base table'; >当然你如果业务流不多,可以直接在后台写个数组即可, > 代码位置详见:tpflow\application\index\controller\Flowdesign.php 第17行
排序值
排序值示意:一个新闻审核可能有多个工作流,或者不同的身份发起有不同的工作流可以供选择,这里的排序值是对应选择的时候的优先。
开始设计审批,点击审批流设计
- 面板上右击,新增步骤
- 鼠标按住步骤的ICO图标,拖动需要链接的工作流
- 即可完成工作流的基本设置
尝试去设计一条视图审批流。接下来,我们进入属性设置。
流程属性
工作流的多样性,决定了工作流的属性较多,但细分起来,除非特殊的要求,不然大部分的工作流还是很有规律的。
- 正常直线型审批流
- 正常多分支型审批流
- 正常的提交同意型审批流
- 回退型审批流
- 会签型审批流
等等多种多样的工作流审批欲看属性,先看数据表结构
-- ---------------------------- -- Table structure for leipi_flow_process -- ---------------------------- DROP TABLE IF EXISTS `leipi_flow_process`; CREATE TABLE `leipi_flow_process` ( `id` int(10) NOT NULL AUTO_INCREMENT, `flow_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '流程ID', `process_name` varchar(255) NOT NULL DEFAULT '' COMMENT '步骤名称', `process_type` char(10) NOT NULL DEFAULT '' COMMENT '步骤类型', `process_to` varchar(255) NOT NULL DEFAULT '' COMMENT '转交下一步骤号', `auto_person` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '本步骤的自动选主办人规则0:为不自动选择1:流程发起人2:本部门主管3指定默认人4上级主管领导5. 一级部门主管6. 指定步骤主办人', `auto_unlock` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否允许修改主办人auto_type>0 0不允许 1允许(默认)', `auto_sponsor_ids` varchar(255) NOT NULL DEFAULT '' COMMENT '3指定步骤主办人ids', `auto_sponsor_text` varchar(255) NOT NULL DEFAULT '' COMMENT '3指定步骤主办人text', `auto_respon_ids` varchar(255) NOT NULL DEFAULT '' COMMENT '3指定步骤主办人ids', `auto_respon_text` varchar(255) NOT NULL DEFAULT '' COMMENT '3指定步骤主办人text', `auto_role_ids` varchar(255) NOT NULL DEFAULT '' COMMENT '制定默认角色ids', `auto_role_text` varchar(255) NOT NULL DEFAULT '' COMMENT '制定默认角色 text', `auto_process_sponsor` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '[保留功能]指定其中一个步骤的主办人处理', `is_sing` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '会签选项0禁止会签1允许会签(默认) ', `sign_look` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '会签可见性0总是可见(默认),1本步骤经办人之间不可见2针对其他步骤不可见', `is_back` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否允许回退0不允许(默认) 1允许退回上一步2允许退回之前步骤', `out_condition` text NOT NULL COMMENT '转出条件', `setleft` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '左 坐标', `settop` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '上 坐标', `style` text NOT NULL COMMENT '样式 序列化', `is_del` tinyint(1) unsigned NOT NULL DEFAULT '0', `updatetime` int(10) unsigned NOT NULL DEFAULT '0', `dateline` int(10) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=87 DEFAULT CHARSET=utf8;
看上面确实比较复杂,给你提取几个重要,并解释下
- flow_id 工作流ID,对应flow
- process_to 工作流下一个步骤id
- auto_person 办理人类型
- is_sing 是否允许会签
- is_back 是否允许回退
- out_condition 转出条件
看到这里,基本上是可以理解开头说的几句话,工作流的复杂性决定了数据表设计的复杂性,但这个地方,我已经调整了N次,且是在巨人的肩膀上,在对数据表设计进行优化
auto_person 就是告诉系统,是按人来审核,还是按部门角色来审核,从而可以发起审批通知
process_to 下一个,out_condition,转出条件这两个其实有点互为替补,out_condition相对要求比较重要。(下面单独描述)
out_condition 转出条件
针对多个一对多的审批流,如下图;那么项目中心审核时,系统就需要调用out_condition对于下个审批人进行判断,到底应该,A、B、C、D那个人人来审核,通知谁
看看代码实现
ProcessDb.php /** * 获取下个审批流信息 * @param $wf_type 单据表 * @param $wf_fid 单据id * @param $pid 流程id **/ public static function GetNexProcessInfo($wf_type,$wf_fid,$pid) { $info = Db::name($wf_type)->find($wf_fid); $nex = Db::name('flow_process')->find($pid); if($nex['process_to'] !=''){ $nex_pid = explode(",",$nex['process_to']); $out_condition = json_decode($nex['out_condition'],true); if(count($nex_pid)>=2){ //多个审批流 foreach($out_condition as $key=>$val){ $where =implode(",",$val['condition']); //根据条件寻找匹配符合的工作流id $info = Db::name($wf_type)->where($where)->where('id',$wf_fid)->find(); if($info){ $nexprocessid = $key; //获得下一个流程的id break; } } $process = self::GetProcessInfo($nexprocessid); }else{ $process = self::GetProcessInfo($nex_pid); } }else{ $process = ['id'=>'','process_name'=>'END','todo'=>'结束']; } return $process; }
out_condition 中关于获取表字段来判断 Flowdesign.php
/*根据获取的数据表字段,进行条件判断*/ private function get_db_column_comment($table_name = '', $field = true, $table_schema = ''){ $database = config('database.'); $table_schema = empty($table_schema) ? $database['database'] : $table_schema; $table_name = $database['prefix'] . $table_name; $fieldName = $field === true ? 'allField' : $field; $cacheKeyName = 'db_' . $table_schema . '_' . $table_name . '_' . $fieldName; $param = [ $table_name, $table_schema ]; $columeName = ''; if($field !== true){ $param[] = $field; $columeName = "AND COLUMN_NAME = ?"; } $res = Db::query("SELECT COLUMN_NAME as field,column_comment as comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ? AND table_schema = ? $columeName", $param); $result=array(); foreach($res as $k =>$value){ foreach($value as $key=>$v){ if($value['comment'] !=''){ $result[$value['field']]=$value['comment']; } } } return count($result) == 1 ? reset($result) : $result; }
工作流驱动
工作流的主要运行方式
本人技术较为一般,所以也只是简化你的工作流开发;把工作流的发起,审核,会签,回退等操作写成一个插件,也可以称作是类库。
如您不嫌弃,可以给我们指点改进方案,我们对此感激不尽。
工作流审核最最最简单的驱动详情
工作流的发起:
通过 application\Index\Controller\Flow.php 及单据字段 status 进行判断
status | 状态示意 |
---|---|
0 | 保存中 |
1 | 流程中 |
2 | 审核通过 |
-1 | 退回修改 |
通过 {:action('flow/btn',['wf_fid'=>$k.id,'wf_type'=>'news','status'=>$k.status])} 的方式调用了以下,从而判断流程是运行状态,或者是其它状态。
public function btn($wf_fid,$wf_type,$status)
{
$url = url("/index/flow/do_check/",["wf_type"=>$wf_type,"wf_title"=>'2','wf_fid'=>$wf_fid]);
$url_star = url("/index/flow/start/",["wf_type"=>$wf_type,"wf_title"=>'2','wf_fid'=>$wf_fid]);
switch ($status)
{
case 0:
return '<span class="btn radius size-S" onclick=layer_show(\'发起工作流\',"'.$url_star.'","450","350")>发起工作流</span>';
break;
case 1:
$st = 0;
$workflow = new workflow();
$flowinfo = $workflow->workflowInfo($wf_fid,$wf_type);
if($flowinfo['process']['auto_person']==4){
$user = explode(",", $flowinfo['process']['auto_sponsor_ids']);
if (in_array($this->uid, $user)) {
$st = 1;
}
}
if($flowinfo['process']['auto_person']==5){
$user = explode(",", $flowinfo['process']['auto_role_ids']);
if (in_array($this->role, $user)) {
$st = 1;
}
}
if($st == 1){
return '<span class="btn radius size-S" onclick=layer_show(\'审核\',"'.$url.'","850","650")>审核</span>';
}else{
return '<span class="btn radius size-S">无权限</span>';
}
break;
default:
return '';
}
}
当然接下来的工作全部就交由工作流去执行判断了。接下来详解。
发起审核
工作流发起审核
我们先来假定一条工作流
测试工作流: A审核完->B审核->C审核结束
- 通过 调用
{:action('flow/btn'}
的方式来启动工作流
public function btn($wf_fid,$wf_type,$status)
{
$url = url("/index/flow/do_check/",["wf_type"=>$wf_type,"wf_title"=>'2','wf_fid'=>$wf_fid]);
$url_star = url("/index/flow/start/",["wf_type"=>$wf_type,"wf_title"=>'2','wf_fid'=>$wf_fid]);
switch ($status)
{
case 0:
return '<span class="btn radius size-S" onclick=layer_show(\'发起工作流\',"'.$url_star.'","450","350")>发起工作流</span>';
break;
case 1:
$st = 0;
$workflow = new workflow();
$flowinfo = $workflow->workflowInfo($wf_fid,$wf_type);
if($flowinfo['process']['auto_person']==4){
$user = explode(",", $flowinfo['process']['auto_sponsor_ids']);
if (in_array($this->uid, $user)) {
$st = 1;
}
}
if($flowinfo['process']['auto_person']==5){
$user = explode(",", $flowinfo['process']['auto_role_ids']);
if (in_array($this->role, $user)) {
$st = 1;
}
}
if($st == 1){
return '<span class="btn radius size-S" onclick=layer_show(\'审核\',"'.$url.'","850","650")>审核</span>';
}else{
return '<span class="btn radius size-S">无权限</span>';
}
break;
default:
return '';
}
}
-
通过 调用
{:action('flow/status'}
的方式来取得工作流的状态。 -
通过
application\Index\Controller\Flow.php Star
及statr_save
两个方法进行启动工作流
/*发起流程,选择工作流*/
public function start()
{
$wf_type = input('wf_type');
$info = ['wf_type'=>input('wf_type'),'wf_title'=>input('wf_title'),'wf_fid'=>input('wf_fid')];
$workflow = new workflow();
$flow = $workflow->getWorkFlow($wf_type);
$this->assign('flow',$flow);
$this->assign('info',$info);
return $this->fetch();
}
/*正式发起工作流*/
public function statr_save()
{
$wf_type = input('wf_type');
$wf_id = input('wf_id');
$wf_fid = input('wf_fid');
$data = $this->request->param();
$workflow = new workflow();
$flow = $workflow->startworkflow($data,$this->uid);
if($flow['code']==1){
return msg_return('Success!');
}
}
可以看到,消息基本上使用了工作流的方法来调用。
这时候,我们已经成功启动了工作流。发起了工作流的审核。
- 通过
application\Index\Controller\Flow.php do_check
及do_check_save
两个方法进行审批,这里我只写出 do_check_save 的核心代码
workflow/workflow.php
function workdoaction($config,$uid)
{
if( @$config['run_id']=='' || @$config['run_flow_process']==''){
throw new \Exception ( "config参数信息不全!" );
}
$taskService = new TaskService();//工作流服务
$wf_actionid = $config['submit_to_save'];
$sing_st = $config['sing_st'];
if($sing_st == 0){
if ($wf_actionid == "ok") {//提交处理
$ret = $taskService->doTask($config,$uid);
} else if ($wf_actionid == "back") {//退回处理
$ret = $taskService->doBack($config,$uid);
} else if ($wf_actionid == "sing") {//会签
$ret = $taskService->doSing($config,$uid);
} else { //通过
throw new \Exception ( "参数出错!" );
}
}else{
$ret = $taskService->doSingEnt($config,$uid,$wf_actionid);
}
return $ret;
}
$wf_actionid = $config['submit_to_save'];
根本上是通过 页面按钮进行判断用户的实际操作,比如操作了回退,那么对应调用了 taskService 的不同方法来执行,详细看如下。
![]()
flow.php do_check_save 调用workflow.php workdoaction 调用TaskService.php 对应的方法回退 BackFlow.php/会签 SingFlow.php/正常 TaskFlow.php调用/workflow/Db数据库驱动去执行操作结束
代码就不一一指出,根据这个流程图,基本上就可以看懂了。
回退会签
工作流回退与会签
回退:简单说就是退回给上一步骤,或者上上步骤甚至是退回给修改
会签:这个相对复杂点,就发起审核的时候,如果审核人对于不确定,需要转给另外一个人进行阅读,那么,采用的是会签。
会签的时候,可能出现以下几种情况
- 会签同意:那么系统结束本次会签,回到下级审批中去
- 会签回退:退回到响应的审核审批或者修改步骤
- 会签再会签:给A2看了,A2还是不能确定,需要在给A3看,那么这就属于会签再会签,简单示意,就是有点类似于自由工作流,我想给谁就转给你。
\extend\workflow\class\command BackFlow.php 工作流回退命令
\extend\workflow\class\command SingFlow.php 工作流会签命令
\extend\workflow\class\commandTaskFlow.php 工作流正常流
在流程设计属性时有两个关键性字段,
is_sing 是否允许会签 is_back 是否允许回退
这两个字段直接控制了 用户的权限。
我们看看前端处理代码,本人前端最差了,不要见笑
\application\Index\View\Flow
html
{if condition='$flowinfo.sing_st == 0'}
<a class="btn btn-primary radius" id='nexbton' onclick='tj("ok")' >提交</a>
<a class="btn btn-primary radius" id='backbton' onclick='tj("back")'value='back' >回退</a>
<a class="btn btn-primary radius" id='singbton' onclick='tj("sing")' value='sing' >会签</a>
{else/}
<a class="btn btn-primary radius" id='nexbton' onclick='sing("sok")' >会签提交</a>
<a class="btn btn-primary radius" id='backbton' onclick='sing("sback")'value='back' >会签回退</a>
<a class="btn btn-primary radius" id='singbton' onclick='sing("ssing")' value='sing' >再会签</a>
{/if}
Js:
function tj(value){
if(value =='back'){
$('#nex_process').hide();//
$('#nexbton').hide();
$('#singbton').hide();
$('#backbton').html('确认回退');
$('#back_process').show();
var select = $('#backflow option:selected').val();
$("#singflow").removeAttr("datatype");
if(select==''){
layer.msg('请选择回退步骤');
return false;
}
}
if(value =='sing'){
$('#nex_process').hide();//
$('#nexbton').hide();
$('#backbton').hide();
$('#backbton').html('确认会签');
$('#sing_process').show();
$("#backflow").removeAttr("datatype");
var select = $('#singflow option:selected').val();
if(select==''){
layer.msg('请选择会签人');
return false;
}
}
if(value =='ok'){
$("#backflow").removeAttr("datatype");
$("#singflow").removeAttr("datatype");
}
$('#submit_to_save').val(value);
$('#forms').submit();
}
function sing(value){
if(value =='sback'){
$('#nex_process').hide();//
$('#nexbton').hide();
$('#singbton').hide();
$('#backbton').html('确认回退');
$('#back_process').show();
var select = $('#backflow option:selected').val();
$("#singflow").removeAttr("datatype");
if(select==''){
layer.msg('请选择回退步骤');
return false;
}
}
if(value =='ssing'){
$('#nex_process').hide();//
$('#nexbton').hide();
$('#backbton').hide();
$('#backbton').html('确认会签');
$('#sing_process').show();
$("#backflow").removeAttr("datatype");
var select = $('#singflow option:selected').val();
if(select==''){
layer.msg('请选择会签人');
return false;
}
}
if(value =='sok'){
$("#backflow").removeAttr("datatype");
$("#singflow").removeAttr("datatype");
}
$('#submit_to_save').val(value);
$('#forms').submit();
}
这就是流程中,通过提交不同的按钮值,来决定退回。
工作流集成
工作流插件集成在你的项目
Thinkphp 5.1+项目
注:Tpflow 本身就基于Thinkphp开发,在集成的时候也相对简单,TP5.1可直接无缝集成;Tp5.0需要做相应的调整,详细见 Tp5.0到5.1的升级指导。
第一步:资源文件移动
将public/static/work 拷贝到你的项目里;(建议完整的将static拷贝到public避免样式出错。部分不需要,或者没有引用的再删除即可。)
将public/static/lib/layer 拷贝到目录下 ;
修改 config/template.php
文件 引入资源文件;若有冲突,自行修改即可
'tpl_replace_string' => [
'__HUI__' => '/static/h-ui',
'__HUIADMIN__' => '/static/h-ui.admin',
'__LIB__' => '/static/lib',
'__Flow__' => '/static/work',
]
第二步:拷贝插件代码
第三步:控制器及视图文件拷贝
控制器: \application\index\controller\Flow.php 、Flowdesign.php
视图文件: \application\index\view flowdesign flow pub
复制通用方法
/**
* ajax数据返回,规范格式
*/
function msg_return($msg = "操作成功!", $code = 0,$data = [],$redirect = 'parent',$alert = '', $close = false, $url = '')
{
$ret = ["code" => $code, "msg" => $msg, "data" => $data];
$extend['opt'] = [
'alert' => $alert,
'close' => $close,
'redirect' => $redirect,
'url' => $url,
];
$ret = array_merge($ret, $extend);
return Response::create($ret, 'json');
}
function ids_parse($str,$dot_tmp=',')
{
if(!$str) return '';
if(is_array($str))
{
$idarr = $str;
}else
{
$idarr = explode(',',$str);
}
$idarr = array_unique($idarr);
$dot = '';
$idstr ='';
foreach($idarr as $id)
{
$id = intval($id);
if($id>0)
{
$idstr.=$dot.$id;
$dot = $dot_tmp;
}
}
if(!$idstr) $idstr=0;
return $idstr;
}
第三步:数据库复制
表前缀根据自己的项目修改。
wf_flow 流程主表
wf_flow_process 流程步骤表
wf_run 运行主表
wf_run_cache 缓存表
wf_run_log 运行日志表
wf_run_process 运行步骤表
wf_run_sign 会签表
特别注意事项
1. 流程设计中的类型:即为wf_type wf_fid 两个关键字段。代码位置在 Flowdesign.php 第16行,这里你可以自定义个$type 数组,或者直接读取数据库。(但必须是数据表,且不含表前缀)
2. 流程设计中的转出条件:转出条件只有在两个下级的时候才会出现,代码由\public\static\work\js\flowdesign\attribute.js 第 206行控制; 转出条件中的字段设计是读取 对应类型表的 字段信息(若字段没有备注,则不会显示);
3. 流程设计中的角色及用户:
wf_role wf_user
为方便演示使用的测试表,正式项目,你需要在Flowdesign.php
第 523 531 536修改你对应的数据表,注意:field('id as vlaue,username as text') 必须这么设置;
4.在你的项目login需要设置两个session 值
Session::set('uid', input('id'));Session::set('role', input('role'));
以确保项目正常运行;
5.Thinkphp 5.0、3.2的项目差别不是非常大,5.0主要个别几个函数 RAW 不一样及where条件会有点不一样,其他基本上不变;3.2的项目相对调整较多,比如 M=》db 等等;
非Thinkphp 项目
1、整体设计方面不需要大的调整,还是按上面教程进行导入,特别要说明的是,因为是基于TP开发,用到了TP的session 、 Db等等方法,建议稍作修改即可。
工作流消息
工作流消息这块还没完全做完,预计集成邮件,短信,及微信等等SDK
表单设计
表单设计器,借鉴了几个大神的写法,主要采用 formbuilder 开源的插件作为前端,借鉴了 tpadmin 代码生成的几个思路,并重构了代码生成。
设计器生成插件位于extend目录下,命名为TPFD(thinkphp form Desings)。
如有任何问题或者建议,烦请跟我们联系:1838188896@qq.cm
使用简要流程图
新增表单表单函数设计(用于表单调用)表单可视化设计代码生成
自定义设计
表单设计的意义
表单设计及自动生成是大型CRM、ERP常见的功能之一,也叫柔性平台。
应用场景:该功能适用于乙方人员新增较为简单的功能模块,如新增个印章使用登记。
应用拓展:支持挂带工作流模块。
- 新增表单模块
- 新增表单函数
- 可视化设计表单
- 表单预览
- 代码生成
先看看数据表结构
DROP TABLE IF EXISTS `leipi_form`;
CREATE TABLE `leipi_form` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL COMMENT '表单名称',
`name` varchar(255) DEFAULT NULL COMMENT '表名',
`file` varchar(255) DEFAULT NULL COMMENT '生成文件',
`menu` int(11) NOT NULL DEFAULT '0',
`flow` int(11) NOT NULL DEFAULT '0',
`ziduan` longtext,
`uid` varchar(255) DEFAULT NULL,
`add_time` int(11) DEFAULT NULL,
`status` int(11) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
重要的代码字段只有 ziduan 这个,当你用界面设计器,完成设计的时候,这个会填上一段JSON
{"fields":[
{"label":"radio测试","field_type":"radio","required":true,"field_options":{"options":[{"label":"女","checked":false},{"label":"男","checked":false}],"size":"small"},"lists":"yes","search":"yes","type":"text","cid":"c2","name":"name2"},
{"label":"选择测试","field_type":"select","required":true,"field_options":{"options":[{"label":"这是选择","checked":true},{"label":"这也是选择2","checked":false},
{"label":"还是选择","checked":false}],"size":"medium"},"lists":"yes","search":"yes","type":"text","cid":"c6","name":"tel2"},
{"label":"日期测试","field_type":"date","required":true,"field_options":{"size":"small"},"lists":"yes","search":"yes","type":"text","cid":"c10","name":"cont2"},
{"label":"姓名2","field_type":"checkbox","required":true,"field_options":{"options":[{"label":"女","checked":false},{"label":"男","checked":false}],"size":"small"},"lists":"yes","search":"yes","type":"text","cid":"c2","name":"name"}]}
> label 字段中文名
> field_type|| type 字段类别
> field_options 字段选项
> size 字段对应大小,目前设计为:6个TD ,
> small 2个TD medium 4个TD large 6个TD
> 系统根据大小及顺序自动排序成表格
> lists 是否列表显示(有些字段不显示在列表)
> search 是否为列表查询字段
> cid 前端ID
> name 数据库字段名,建议不要中文()
> status uid add_time 三个字段系统已经自动内置,不允许重复!
样式属性
刚才JSON生成的表单样式
代码生成
代码生成
代码生成借鉴了开源软件 tpadmin的代码生成思路
废弃了一些不需要的写法,整合了formdesign得设计
重新命名:TPFD
使用说明
跟工作流一样优雅,只需要两句话,剩下的交由插件去解决。
@$data 需要的数据
@demo 需要生成的文件(all 全部,demo 预览)
$tpdf = new tpdf();
$tpdf->make($data,'demo');
特别注意:
正式部署项目的时候,需要把控制器、数据表列入黑名单,以防不小心替换了系统的控制器,导致系统出错。!!!!
附录
TpFlow 是由“Pms研发团队”结合leipi工作流及phpworkflow等特性结合开发的一款thinkphp5.1/php的工作流插件**
一个人造轮子......
感谢:
感谢前端UI框架:HUI
感谢leipi流程设计器的思路及部分代码;
感谢phpworkflow 给的流程设计思路
开发团队成员信息
逆天的蝈蝈 QQ:632522043
交流群:532797225
作者博客:http://www.cojz8.com/
代码托管:https://gitee.com/ntdgg/tpflow