thinkphp5集成H-ui后台(二)整合并使用ztree,完成树形页面功能

2 篇文章 0 订阅
1 篇文章 0 订阅

与其说tp5整合ztree,不如说介绍ztree如何具体使用来得明了,这里面tp5只要在后台查询并处理成ztree所需的json格式数据就行。
ztree的样式和功能多样,有疑问的可以仔细阅读api。
刚开始接触ztree的时候,有一种思维的局限,总喜欢以父节点为起点,去推算它所包含的子孙节点。这样做虽然可以达到目的,但算法确实有些麻烦,尤其是使用递归的方式(说起递归,我个人觉得总是有种豁然开朗的感觉,大概是我的逻辑思维太弱吧。在增加博客的时候会用到,这里不多描述)。但ztree给我一种新的思维方式,那就是,无论当前节点有多少个子孙节点,它一定只有一个父节点,如此从下往上推,每个节点只要能够找到自己的父节点就行。这样的话,我们只要封装好每个节点,其余的事,就都交给ztree了。
1、树型结构的数据库表设计
按上面的思路,设计中加一个自连接的字段(parent_id),其余的按自己功能需要增加就行。这里我直接上sql

CREATE TABLE `mq_blog_category` (
  `id` tinyint(4) NOT NULL AUTO_INCREMENT COMMENT '逻辑主键',
  `cname` varchar(60) DEFAULT NULL COMMENT '分类名称',
  `order_num` tinyint(4) DEFAULT NULL COMMENT '排列顺序',
  `remark` varchar(200) DEFAULT NULL COMMENT '备注',
  `parent_id` int(11) DEFAULT NULL COMMENT '父ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4;


-- ----------------------------
-- Records of mq_blog_category
-- ----------------------------
INSERT INTO `mq_blog_category` VALUES ('1', 'it', '1', '', '0');
INSERT INTO `mq_blog_category` VALUES ('2', 'java', '2', null, '1');
INSERT INTO `mq_blog_category` VALUES ('3', '文学', '3', null, '0');
INSERT INTO `mq_blog_category` VALUES ('4', 'php', '4', null, '1');
INSERT INTO `mq_blog_category` VALUES ('5', '.net', '3', 'dsfdddd', '1');
INSERT INTO `mq_blog_category` VALUES ('6', '《花前月下,青丝白发》', '1', '周作人散文精选集', '3');
INSERT INTO `mq_blog_category` VALUES ('7', 'oracle', '4', '', '1');
INSERT INTO `mq_blog_category` VALUES ('9', 'mysql', '5', '', '1');
INSERT INTO `mq_blog_category` VALUES ('10', 'sqlServer', '1', '', '1');

关于tp5的数据库配置,这里不多说明,这里直接上当前系统的代码,在database.php文件中

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------


return [
    // 数据库类型
    'type'            => 'mysql',
    // 服务器地址
    'hostname'        => '127.0.0.1',
    // 数据库名
    'database'        => 'mqblog',
    // 用户名
    'username'        => 'root',
    // 密码
    'password'        => 'xxxx',
    // 端口
    'hostport'        => '',
    // 连接dsn
    'dsn'             => '',
    // 数据库连接参数
    'params'          => [],
    // 数据库编码默认采用utf8
    'charset'         => 'utf8',
    // 数据库表前缀
    'prefix'          => 'mq_',
    // 数据库调试模式
    'debug'           => true,
    // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
    'deploy'          => 0,
    // 数据库读写是否分离 主从式有效
    'rw_separate'     => false,
    // 读写分离后 主服务器数量
    'master_num'      => 1,
    // 指定从服务器序号
    'slave_no'        => '',
    // 是否严格检查字段是否存在
    'fields_strict'   => true,
    // 数据集返回类型
    'resultset_type'  => 'array',
    // 自动写入时间戳字段
    'auto_timestamp'  => false,
    // 时间字段取出后的默认时间格式
    'datetime_format' => 'Y-m-d H:i:s',
    // 是否需要进行SQL性能分析
    'sql_explain'     => false,
];

2、博客分类开发说明

 

1)引入ztree相关资源

 

<link rel="stylesheet" href="__ADMIN__/lib/zTree/v3/css/zTreeStyle/zTreeStyle.css" type="text/css">
<script type="text/javascript" src="__ADMIN__/lib/zTree/v3/js/jquery.ztree.all-3.5.min.js"></script> 

2)树型数据封装与展示
表设计的时候已经是按照ztree的格式,所以只要直接查询出结果就行。然后让ztree中的node属性是id,name,pId(注意驼峰)对应于结果集中的字段值就行。这里设计的时候没有计划将根节点放入数据库中,所以在php代码中创建一个根节点对象。另外就是对于根节点,ztree也提供了一些图标,我们根据自己的喜好放置图片地址就行。请看下面代码:

/**
 * 异步加载树型结构数据
 * 1、查询博客分类列表
 * 2、封装节点成json格式数据
 * */
public function getTreeData(Request $request){
    //查询所有的博客分类
    $categoryList = BlogCategory::all();
    
    
    $nodeArr = array();
    
    //创建一个根节点(也可以直接存放在数据库中,这里为了演示一些模块config的配置)
    $rootNode = new Object_();
    $rootNode->id = 0;
    $rootNode->name = config('ztree_root_name');//全部分类,就是根节点的名称
    $rootNode->open = true;
    /*
     *config('icon_open')、config('icon_close')
     *分别对应于
     *'icon_open' => '/static/admin/lib/zTree/v3/css/zTreeStyle/img/diy/1_open.png',
     *'icon_close' => '/static/admin/lib/zTree/v3/css/zTreeStyle/img/diy/1_close.png',
     *这两张图片
     */
    $rootNode->iconOpen = $request->root(true).config('icon_open');
    $rootNode->iconClose = $request->root(true).config('icon_close');
    
    array_push($nodeArr, $rootNode);
    
    foreach ($categoryList as $blogCategory){
        $rootNode = new Object_();
        $rootNode->id = $blogCategory->id;
        $rootNode->name = $blogCategory->cname;
        $rootNode->open = false;
        $rootNode->pId = $blogCategory->parent_id;
        
        array_push($nodeArr, $rootNode);
    }
    
    return json_encode($nodeArr);       
}	

那么前端的话就只要获取这个json结果集就行,关于ztree的一些具体说明,我这边就写在代码的注释当中,请参考以下代码:
html代码:

<table class="table">
	<tr>
		<td width="300" class="va-t">
			<ul id="bcTree" class="ztree" style=""></ul>
			<div style="margin-left: 30px">
				<button class="btn btn-primary " onclick="category_add()" type="button">新增</button>
				<button class="btn btn-secondary " onclick="category_edit(1)" type="button">修改</button>
				<button class="btn btn-danger " onclick="category_del()" type="button">删除</button>	
			</div>				
		</td>
		<!-- 增加、修改、查看页面放置在这边的iframe中 -->
		<td class="va-t"><iframe ID="cIframe" Name="cIframe" FRAMEBORDER=0 SCROLLING=AUTO width=100%  height=390px SRC="__URL__/blogCategory/categoryEdit?id=0&flag=0"></iframe></td>
	</tr>
</table>

js代码:

var zTreeObj;


var setting = {
		view : {
			showIcon : true,//是否显示图标
			dblClickExpand : false,//是否双击展开/收起
			selectedMulti : false,//是否允许同时选中多个节点
			expandSpeed : 'fast',//展开速度fast、slow
			showTitle : true, //是否显示节点的title提示信息
			showLine: true,//是否显示节点间的连线
			nameIsHTML : true //设置 name 属性是否支持 HTML 脚本
		},
		data : {
			keep : {
				parent : true
			},
			simpleData : {
				enable : true,
				idKey : "id",
				pIdKey : "pId"
			}
		},
		
		callback : {
			/* 鼠标单击事件,判断是否是导航栏,然后跳转到展示页面 */
			onClick : function(event, treeId, treeNode, clickFlag) {
				var nodes = zTreeObj.getSelectedNodes();
				
				//这里的逻辑是为修改和查看所预备的hidden
				$("#checkNodeId").val(nodes[0].id);
				$("#checkNodePid").val(nodes[0].pId);
				
				//默认进入查看页面
				category_edit(0);
			}
		}
		
};


function initTree() {
	jQuery.ajax({
		url : "__URL__/blogCategory/getTreeData",
		data : {},
		type : "POST",
		dataType : "json",
		cache : false,
		success : function(data) {
			data = eval(data);//ztree只认js对象,而不是字符串,所以eval转换下
			zTreeObj = $.fn.zTree.init($("#bcTree"), setting, data);
			$.fn.zTree.init($("#bcTree"), setting, data);
			var treeObj = $.fn.zTree.getZTreeObj("tree");			
		}
	});
}


$(document).ready(function(){
	initTree();
});

到这一步,就可以达到以下效果了:

3)在ztree上面的CURD
剩下的就是增删改查了。值得说明的是,H-ui这边使用的都是ajax的交互方式,通过js处理的样式就花哨一些。这里没有太多的技术说明,只要懂js和ajax就行,只是提一点,通过ajax请求php返回的结果集是json格式的字符串,而在js中需要通过eval函数处理成js所能认识的对象。但我们这里是个例外,由于使用了iframe,所以就直接在iframe中同步的curd了。这里也上一些参考的代码:

//添加博客分类
function category_add(){
	var cId = $("#checkNodeId").val();
	
	if(cId == ""){
		layer.alert("请选择一个博客分类");
		return;
	}
	
	$("#cIframe").prop("src","__URL__/blogCategory/toCategoryAdd?id=" + cId);
}


//查看、编辑博客分类
function category_edit(flag){
	var cId = $("#checkNodeId").val();
	
	if(cId == ""){
		layer.alert("请选择一个博客分类");
		return;
	}
	
	//修改和完成所有的信息技术
	if(flag == '1' && $("#checkNodePid").val() == ""){
		layer.alert("根博客分类不能修改");
		return;
	}
	
	$("#cIframe").prop("src","__URL__/blogCategory/categoryEdit?id=" + cId + "&flag=" + flag);
}


//删除博客分类
function category_del(){
	
	var cId = $("#checkNodeId").val();
	
	if(cId == ""){
		layer.alert("请选择一个博客分类");
		return;
	}
	
	if($("#checkNodePid").val() == ""){
		layer.alert("根博客分类不能删除");
		return;
	}
	
	
	layer.confirm("该操作将删除当前博客分类和所包含的子博客分类,您确定删除吗?",function(){
		$.ajax({
			url:"__URL__/blogCategory/categoryDel",
			data : {"id":cId},
			type : "POST",
			dataType : "json",
			cache : false,
			success : function(data) {
				if(eval(data)){
            		layer.msg('删除成功',{icon:1,time:1000},function(){
            			window.location.reload();
            		});
            	}else{
            		layer.alert('删除失败');
            	}    		
			}
		});
	});
}

以上代码只是提供思路和核心说明,不要无脑的复制,自己动手,丰衣足食

2019-03-20补充:

有些小伙伴们提到以下代码中的Object_()无法创建,原因是少了对Object_的引入。加上引入代码就可以了。

use phpDocumentor\Reflection\Types\Object_;
use phpDocumentor\Reflection\Types\Object_;

...

    $nodeArr = array();
        
    //创建一个根节点(也可以直接存放在数据库中,这里为了演示一些模块config的配置)
    $rootNode = new Object_();
    $rootNode->id = 0;
    $rootNode->name = config('ztree_root_name');
    $rootNode->open = true;
    $rootNode->iconOpen = $request->root(true).config('icon_open');
    $rootNode->iconClose = $request->root(true).config('icon_close');

...

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值