首先介绍我实现的是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. Servlet部署项目和项目起别名

    一.部署项目: ① 单机MyEclipse导航栏下方Deploy MyEclipse J2EE Project to Server... ②单机Add,选择Service,点击Ok 二.给项目起别名: ...

  2. Java基础知识笔记第九章:组件及事件处理

    java Swing 图形用户界面(GUI : Graphics User Interface) 窗口 JFrame常用方法 JFrame()创建一个无标题的窗口. JFrame(String s)创 ...

  3. GitHub 网站汉化

    居然是一个中文Github网站!该不会是个假的吧? 2018-09-03 17:30 前几天分享了一篇文章——3个搜索技巧!在 GitHub上快速找到实用资源!眼尖心细的读者发现了文中的Github网 ...

  4. 如何用C++读取图片中的像素

    来源:https://bbs.csdn.net/topics/391956973  3楼 #include <iostream> #include <fstream> #inc ...

  5. 树莓派4B踩坑指南 - (4)输入法和字体

    输入法和字体 fcitx 安装谷歌输入法和sunpinyin,哪个不用可以装完卸载: sudo apt-get install fcitx fcitx-googlepinyin fcitx-modul ...

  6. spm_hrf

    a=spm_hrf(0.72); n1=MOTOR_taskdesign(1,:);cn1=conv(n1,a);plot(cn1); block design hrf

  7. 阿里云服务器ubantu创建新用户登录显示问题

    在root用户下输入:vi /etc/passwd,找到添加的用户,在后面加上/bin/bash 重新登录即回复正常

  8. 傅盛读书笔记:下一个Moonshot是什么?

    猎豹移动CEO 傅盛 九月底,我有幸在硅谷拜访了苹果前CEO斯卡利.老人如今已经75岁高龄,但看起来仍充满活力.他花了一上午的时间跟我们沟通,非常谦和.平等.坦诚,给我留下了很深的印象.末了,给我们介 ...

  9. python词云图与中文分词

    2019-12-12中文文本分词和词云图具体功能介绍与学习代码: import jiebaa="由于中文文本的单词不是通过空格或者标点符号来进行分割"#jieba.lcut()s是 ...

  10. PaperReading20200222

    CanChen ggchen@mail.ustc.edu.cn   VS-GAE Motivation: With the publication of NAS101, researchers can ...