首先介绍我实现的是xhprof插件的日志转为无限树状图,先看效果图:

废话不多说,直接看代码:(辛辛苦苦敲了好久才搞定,逻辑比较多,新手多揣摩)

控制器:

  1 <?php
2
3 namespace Admin\Controller;
4
7
8 class XhprofController extends AdminbaseController
9 {
10 function _initialize()
11 {
12 parent::_initialize();
13 }
14
15 //获取当前文件目录
16 public function index()
17 {
18 $file = scandir("./public");
19 $str = ".xhprof";
20 foreach ($file as $value) {
21 if (preg_replace("/($str)/", "", $value) != $value) {
22 $dir[] = $value;
23 }
24 }
25 // $count = count($dir);
26 // $page = $this->page($count, 20);
27 // $this -> assign( "Page", $page->show( 'Admin' ) );
28 $this->assign("dir", $dir);
29 $this->display();
30 }
31
32 //获取适当的结构
33 public function tree($file_name)
34 {
35 $file_path = "./public/xhprof/$file_name";
36 $file_name = str_replace('.', '', $file_name);
37 if (F($file_name)) {
38 $mainTree = F($file_name);
39 } else {
40 if (file_exists($file_path)) {
41 $fp = fopen($file_path, "r");
42 $str = fread($fp, filesize($file_path));//指定读取大小,这里把整个文件内容读取出来
43 $array = json_decode($str, true);
44 $array_keys = array_keys($array);
45 //按照调用者整理数据
46 $calls = [];
47 foreach ($array_keys as $array_key) {
48 $caller = explode("==>", $array_key)[0];
49 $beCall = explode("==>", $array_key)[1];
50 if (!$calls[$caller]) {
51 $calls[$caller] = [
52 "caller" => $caller,
53 "beCalls" => []
54 ];
55 }
56 $status = 0;//是否有子目录
57 foreach ($array_keys as $keyv) {
58 if (strpos($keyv, $beCall . '==>') !== false && strpos($keyv, "@") === false && $beCall !== null && $beCall !== "count") {
59 $status = 1;
60 }
61 }
62 if ($beCall !== null) {
63 $calls[$caller]['beCalls'][] = array('name' => $beCall, "status" => $status, 'data' => $array[$array_key]);
64 }
65 }
66 foreach ($calls as &$v) {
67 $tmpAll = 0;
68 foreach ($v['beCalls'] as $vv) {
69 $tmpAll += $vv['data']['wt'];
70 }
71 foreach ($v['beCalls'] as &$vv1) {
72 $vv1['data']['wtp'] = round($vv1['data']['wt'] * 100 / $tmpAll, 2);
73 $vv1['wtp'] = $vv1['data']['wt'];
74 }
75 }
76 $mainTree = $calls;
77 //缓存$mainTree
78 F($file_name, $mainTree);
79 } else {
80 $mainTree = "";
81 }
82 }
83 array_multisort(array_column($mainTree["main()"]["beCalls"], "wtp"), SORT_DESC, array_column($mainTree["main()"]["beCalls"], "name"), SORT_DESC, $mainTree["main()"]["beCalls"]);
84 $this->assign("main", $array["main()"]);
85 $this->assign("mainTree", $mainTree["main()"]);
86 $this->assign("level", 1);
87 $this->assign("file_name", $file_name);
88 $this->assign("file_path", $file_path);
89 $this->display();
90 }
91
92 public function ajax()
93 {
94 $note = htmlspecialchars_decode(I("post.note"));
95 $file_name = htmlspecialchars_decode(I("post.file_name"));
96 $file_path = htmlspecialchars_decode(I("post.file_path"));
97 //处理$mainTree
98 if (F($file_name)) {
99 $mainTree = F($file_name);
100 } else {
101 if (file_exists($file_path)) {
102 $fp = fopen($file_path, "r");
103 $str = fread($fp, filesize($file_path));//指定读取大小,这里把整个文件内容读取出来
104 $array = json_decode($str, true);
105 $array_keys = array_keys($array);
106 //按照调用者整理数据
107 $calls = [];
108 foreach ($array_keys as $array_key) {
109 $caller = explode("==>", $array_key)[0];
110 $beCall = explode("==>", $array_key)[1];
111 if (!$calls[$caller]) {
112 $calls[$caller] = [
113 "caller" => $caller,
114 "beCalls" => []
115 ];
116 }
117 $status = 0;//是否有子目录
118 foreach ($array_keys as $keyv) {
119 if (strpos($keyv, $beCall . '==>') !== false && strpos($keyv, "@") === false && $beCall !== null && $beCall !== "count") {
120 $status = 1;
121 }
122 }
123 if ($beCall !== null) {
124 $calls[$caller]['beCalls'][] = array('name' => $beCall, "status" => $status, 'data' => $array[$array_key]);
125 }
126 }
127 foreach ($calls as &$v) {
128 $tmpAll = 0;
129 foreach ($v['beCalls'] as $vv) {
130 $tmpAll += $vv['data']['wt'];
131 }
132 foreach ($v['beCalls'] as &$vv1) {
133 $vv1['data']['wtp'] = round($vv1['data']['wt'] * 100 / $tmpAll, 2);
134 $vv1['wtp'] = $vv1['data']['wt'];
135 }
136 }
137 $mainTree = $calls;
138 //缓存$mainTree
139 F($file_name, $mainTree);
140 } else {
141 $mainTree = "";
142 }
143 }
144 array_multisort(array_column($mainTree[$note]["beCalls"], "wtp"), SORT_DESC, array_column($mainTree[$note]["beCalls"], "name"), SORT_DESC, $mainTree[$note]["beCalls"]);
145 $this->ajaxReturn($mainTree[$note]);
146 }
147
148
149 }

veiw界面:

 </head>
<body>
<div class="wrap">
<ul class="nav nav-tabs">
<li class="active"><a href="">{:L('ADMIN_XHPROF')}</a></li>
</ul>
<form method="post" class="js-ajax-form" action="{:U('AdminTerm/listorders')}">
<table class="table table-hover table-bordered table-list">
<thead>
<tr>
<th width="2">ID</th>
<th width="50">{:L('FILE_NAME')}</th>
</tr>
</thead>
<tbody>
<volist name="dir" id="vo" key="k">
<tr>
<th width="2">{$k}</th>
<th width="50"><a href="{:U('admin/xhprof/tree',array('file_name'=>$vo))}">{$vo}</a></th>
</tr>
</volist>
</tbody>
<tfoot>
<tr>
<th width="2">ID</th>
<th width="50">{:L('FILE_NAME')}</th>
</tr>
</tfoot>
</table>
<div class="pagination">{$Page}</div>
</form>
</div>
<script src="__PUBLIC__/js/common.js"></script>
</body>
</html>
  1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
4 <title>Xhprof数据分析</title>
5 <link rel="stylesheet" type="text/css" href="__TMPL__Public/assets/css/bootstrap.min.css"/>
6 <link rel="stylesheet" type="text/css" href="__TMPL__Public/assets/css/xhprof.css"/>
7 <script type="text/javascript" src="__PUBLIC__/js/jquery.js"></script>
8 </head>
9 <body>
10 <div class="tree well">
11 <ul>
12 <li>
13 <span class="main">
14 <i class='icon-minus'> </i> <b class="name">main()</b>
15 第<b>&nbsp;1&nbsp;</b>级&emsp;&emsp;&emsp;
16 ct:<b class="bw">{$main.ct}</b>
17 wt:<b class="red" >{$main.wt} (100%)</b>
18 cpu:<b class="bw">{$main.cpu}</b>
19 mu:<b class="bw">{$main.mu}</b>
20 pmu:<b class="bw">{$main.pmu}</b>
21 </span>
22 <foreach name="mainTree['beCalls']" item="vo">
23 <ul>
24 <li class='parent_li'>
25 <span title='Collapse this branch' note="{$vo.name}" level="2" file_name={$file_name} file_path={$file_path}>
26 <if condition="$vo['status']==1">
27 <i class="icon-plus"></i>
28 <else/>
29 <b style='width:14px;display: inline-block;'></b>
30 </if>
31 <div style="display: inline-block;">
32 <b class="name" title={$vo.name}>{$vo.name}</b>
33 第<b>&nbsp;2&nbsp;</b>级&emsp;&emsp;&emsp;
34 ct:<b class="ct">{$vo.data.ct}</b>
35 <if condition="$vo['data']['wtp'] gt 10">
36 wt:<b class="red">{$vo.data.wt} ({$vo.data.wtp|round=2}%)</b>
37 <else/>
38 wt:<b class="wt" style="display: inline-block;min-width: 150px;">{$vo.data.wt} ({$vo.data.wtp|round=2}%)</b>
39 </if>
40 cpu:<b class="bw">{$vo.data.cpu}</b>
41 mu:<b class="bw">{$vo.data.mu}</b>
42 pmu:<b class="bw">{$vo.data.pmu}</b>
43 </div>
44 </span>
45 </li>
46 </ul>
47 </foreach>
48 </li>
49 </ul>
50 </div>
51 </body>
52 <script>
53 $(function () {
54 $('.tree li:has(ul)').addClass('parent_li').find(' > span').attr('title', 'Collapse this branch');
55 $('body').on('click', "span", function (e) {
56 e.stopPropagation();
57 if ($(this).attr('is_click') === 1) {
58 return false;
59 }
60 $(this).attr('is_click', 1);
61 var children = $(this).parent('li.parent_li').find(' > ul > li');
62 if (children.is(":visible")) {
63 children.hide('fast');
64 $(this).attr('title', 'Expand this branch').find(' > i').addClass('icon-plus').removeClass('icon-minus');
65 $(this).attr('is_click', 0);
66 } else {
67 children.show('fast');
68 $(this).attr('title', 'Collapse this branch').find(' > i').addClass('icon-minus').removeClass('icon-plus');
69 if ($(this).hasClass('main')) {
70 $(this).attr('is_click', 0);
71 return;
72 }
73 if (!$(this).siblings('.child').length) {
74 do_ajax($(this));
75 } else {
76 $(this).attr('is_click', 0);
77 }
78 }
79 });
80
81 function do_ajax(e) {
82 var note_js = e.attr('note');
83 var level_js = e.attr('level');
84 var file_name_js = e.attr('file_name');
85 var file_path_js = e.attr('file_path');
86 $.ajax({
87 type: "post",
88 cache: false,
89 dataType: "json",
90 url: "{:U('Admin/Xhprof/ajax')}",
91 data: {
92 note: note_js,
93 level: level_js,
94 file_name: file_name_js,
95 file_path: file_path_js
96 },
97 success: function (data) {
98 if (data.beCalls !== null) {
99 var str = "";
100 for (var i = 0; i < data.beCalls.length; i++) {
101 str += "<ul class='child'>";
102 str += "<li class='parent_li'>";
103 str += "<span title='Collapse this branch' class='load' note=" + data.beCalls[i].name + " level= " + eval(Number(level_js) + 1) + " file_name= " + file_name_js + " file_path= " + file_path_js + ">";
104 if (data.beCalls[i].status == 1) {
105 str += "<i class='icon-plus' ></i>";
106 } else {
107 str += "<b style='width:14px;display: inline-block;'> </b>";
108 }
109 str += "<b class='name' title="+ data.beCalls[i].name + ">" + data.beCalls[i].name + '</b>第<b>&nbsp;' + eval(Number(level_js) + 1) + "</b>&nbsp;级&emsp;&emsp;&emsp;ct:<b class='ct'>" + data.beCalls[i].data.ct + "</b> wt:<b class= " + (data.beCalls[i].data.wtp < 10 ? 'wt' : 'red') + " >" + data.beCalls[i].data.wt + "(" + data.beCalls[i].data.wtp + "%)</b> cpu:<b class='bw' >" + data.beCalls[i].data.cpu + "</b> mu:<b class='bw'>" + data.beCalls[i].data.mu + "</b> pmu:<b class='bw'>" + data.beCalls[i].data.pmu + "</b></span>";
110 str += '</li>';
111 str += '</ul>';
112 }
113 e.siblings('.child').remove();
114 e.after(str);
115 e.attr('is_click', 0);
116 }
117 },
118 error: function () {
119 }
120 })
121 }
122 });
123 </script>
124 </html>

php+ajax 实现无限树列表的更多相关文章

  1. Android 高级UI设计笔记09:Android如何实现无限滚动列表

    ListView和GridView已经成为原生的Android应用实现中两个最流行的设计模式.目前,这些模式被大量的开发者使用,主要是因为他们是简单而直接的实现,同时他们提供了一个良好,整洁的用户体验 ...

  2. 在Bootstrap开发框架中使用bootstrapTable表格插件和jstree树形列表插件时候,对树列表条件和查询条件的处理

    在我Boostrap框架中,很多地方需要使用bootstrapTable表格插件和jstree树形列表插件来共同构建一个比较常见的查询界面,bootstrapTable表格插件主要用来实现数据的分页和 ...

  3. Python无限元素列表实例教程

    有关Python中无限元素列表的实现方法. 本文实例讲述了Python怎么实现无限元素列表的方法,具体实现可使用Yield来完成.下面所述的2段实例代码通过Python Yield 生成器实现了简单的 ...

  4. Android 高级UI设计笔记09:Android实现无限滚动列表

    1. 无限滚动列表应用场景: ListView和GridView已经成为原生的Android应用实现中两个最流行的设计模式.目前,这些模式被大量的开发者使用,主要是因为他们是简单而直接的实现,同时他们 ...

  5. 【js】我们需要无限滚动列表吗?

    无限滚动列表,顾名思义,是能够无限滚动的列表(愿意是指那些能够不断缓冲加载新数据的列表的).但是,我们真的需要这样一个列表吗?在PC端,浏览器的性能其实已经能够满足海量dom节点的渲染刷新(笔者经过简 ...

  6. Thinkphp+Ajax带关键词搜索列表无刷新分页实例

    Thinkphp+Ajax带关键词搜索列表无刷新分页实例,两个查询条件,分页和搜索关键字,懂的朋友还可以添加其他分页参数. 搜索#keyword和加载内容区域#ajax_lists <input ...

  7. DevExpress ASP.NET Core v19.1版本亮点:数据网格和树列表

    行业领先的.NET界面控件DevExpress 发布了v19.1版本,本文将以系列文章的方式为大家介绍DevExpress ASP.NET Core Controls v19.1中新增的一些控件及增强 ...

  8. 循序渐进VUE+Element 前端应用开发(8)--- 树列表组件的使用

    在我前面随笔<循序渐进VUE+Element 前端应用开发(6)--- 常规Element 界面组件的使用>里面曾经介绍过一些常规的界面组件的处理,主要介绍到单文本输入框.多文本框.下拉列 ...

  9. Vue组件封装之无限滚动列表

    无限滚动列表:分为单步滚动和循环滚动两种方式 <template> <div class="box" :style="{width:widthX,hei ...

随机推荐

  1. typeof方法重写(区分数组对象)

    为什么要重写typeof方法? typeof 可以准确的判断除object以外的基础数据类型,但不能区分object类型的具体类型,比如 Array .Date.NULL.NaN 以及自定义类. 观察 ...

  2. 单链表 C++ 实现 - 含虚拟头节点

    本文例程下载链接:ListDemo 链表 vs 数组 链表和数组的最大区别在于链表不支持随机访问,不能像数组那样对任意一个(索引)位置的元素进行访问,而需要从头节点开始,一个一个往后访问直到查找到目标 ...

  3. 小白笔记:Git入门之常见命令

    安装 这里就不介绍安装了,度娘一大堆,找不到可以去找谷爹(前提是你能找到).安装好就跟着笔记进行下一步 准备工作 首先我们需要一个可以 git 的东西,所以我们需要一个文件夹和一个文件 创建文件夹 t ...

  4. 七 Spring的IOC的注解方式

    Spring的IOC的注解方式入门 引入注解约束,配置组件扫描 类上的注解: @Conponent  @Controller @Service @Repository 普通属性的注解   @value ...

  5. BurpSuite pro v2.0.11版

    下载地址: 链接:https://pan.baidu.com/s/1CgXgK_lV2OWjRT364hvfog 提取码:gvxy BurpSuite介绍 借用一下吾爱破解文章中的描述信息:https ...

  6. Python数据类型-4 列表

    列表 列表是Python中最基本也是最常用的数据结构之一.列表中的每个元素都被分配一个数字作为索引,用来表示该元素在列表内所排在的位置.第一个元素的索引是0,第二个索引是1,依此类推. Python的 ...

  7. LeetCode 680. Valid Palindrome II(双指针)

    题意:给定一个字符串,可以最多去掉一个字符,判断是否可以使该字符串成为一个回文串. 分析:head和tail双指针分别指向字符串首尾,如果s[head] != s[tail],则要么去掉s[head] ...

  8. 820复试算法 快排找第 k 小

    done {20-01-30 12:56} ref: https://blog.csdn.net/fengsigaoju/article/details/50728588 note: void qui ...

  9. 02-10Android学习进度报告十

    今天我学习了有关ListView的基础知识,主要是学习了其中界面展示的基本方法. 首先看一个简单的列表实现代码: public class Animal { private String aName; ...

  10. 分布式事务中间件 TCC-Transaction 源码分析 —— 项目实战

    https://blog.csdn.net/lldouble/article/details/79455172